aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/pgarchivecleanup.sgml12
-rw-r--r--src/bin/pg_archivecleanup/pg_archivecleanup.c23
-rw-r--r--src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl118
3 files changed, 115 insertions, 38 deletions
diff --git a/doc/src/sgml/ref/pgarchivecleanup.sgml b/doc/src/sgml/ref/pgarchivecleanup.sgml
index 09991c2fcdd..cd8f49b1c5b 100644
--- a/doc/src/sgml/ref/pgarchivecleanup.sgml
+++ b/doc/src/sgml/ref/pgarchivecleanup.sgml
@@ -94,6 +94,18 @@ pg_archivecleanup: removing file "archive/00000001000000370000000E"
<variablelist>
<varlistentry>
+ <term><option>-b</option></term>
+ <term><option>--clean-backup-history</option></term>
+ <listitem>
+ <para>
+ Remove backup history files as well.
+ See <xref linkend="backup-base-backup"/> for details about backup
+ history files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-d</option></term>
<term><option>--debug</option></term>
<listitem>
diff --git a/src/bin/pg_archivecleanup/pg_archivecleanup.c b/src/bin/pg_archivecleanup/pg_archivecleanup.c
index 3533c9b1ab0..2c3b301f3bc 100644
--- a/src/bin/pg_archivecleanup/pg_archivecleanup.c
+++ b/src/bin/pg_archivecleanup/pg_archivecleanup.c
@@ -23,6 +23,8 @@ const char *progname;
/* Options and defaults */
bool dryrun = false; /* are we performing a dry-run operation? */
+bool cleanBackupHistory = false; /* remove files including backup
+ * history files */
char *additional_ext = NULL; /* Extension to remove from filenames */
char *archiveLocation; /* where to find the archive? */
@@ -104,18 +106,20 @@ CleanupPriorWALFiles(void)
* archive */
/*
- * 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.)
+ * Truncation is essentially harmless, because we skip files whose
+ * format is different from WAL files and backup history files. (In
+ * principle, one could use a 1000-character additional_ext and get
+ * trouble.)
*/
strlcpy(walfile, xlde->d_name, MAXPGPATH);
TrimExtension(walfile, additional_ext);
/*
- * Ignore anything does that not look like a WAL segment or a .partial
- * WAL segment.
+ * Ignore anything does that not look like a WAL segment, a .partial
+ * WAL segment or a backup history file (if requested).
*/
- if (!IsXLogFileName(walfile) && !IsPartialXLogFileName(walfile))
+ if (!IsXLogFileName(walfile) && !IsPartialXLogFileName(walfile) &&
+ !(cleanBackupHistory && IsBackupHistoryFileName(walfile)))
continue;
/*
@@ -256,6 +260,7 @@ usage(void)
printf(_("Usage:\n"));
printf(_(" %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"), progname);
printf(_("\nOptions:\n"));
+ printf(_(" -b, --clean-backup-history clean up files including backup history files\n"));
printf(_(" -d, --debug generate debug output (verbose mode)\n"));
printf(_(" -n, --dry-run dry run, show the names of the files that would be\n"
" removed\n"));
@@ -281,6 +286,7 @@ int
main(int argc, char **argv)
{
static struct option long_options[] = {
+ {"clean-backup-history", no_argument, NULL, 'b'},
{"debug", no_argument, NULL, 'd'},
{"dry-run", no_argument, NULL, 'n'},
{"strip-extension", required_argument, NULL, 'x'},
@@ -306,10 +312,13 @@ main(int argc, char **argv)
}
}
- while ((c = getopt_long(argc, argv, "dnx:", long_options, NULL)) != -1)
+ while ((c = getopt_long(argc, argv, "bdnx:", long_options, NULL)) != -1)
{
switch (c)
{
+ case 'b': /* Remove backup history files as well */
+ cleanBackupHistory = true;
+ break;
case 'd': /* Debug mode */
pg_logging_increase_verbosity();
break;
diff --git a/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl b/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl
index cc3386d1464..18a82ff002e 100644
--- a/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl
+++ b/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl
@@ -12,22 +12,46 @@ program_options_handling_ok('pg_archivecleanup');
my $tempdir = PostgreSQL::Test::Utils::tempdir;
-my @walfiles = (
- '00000001000000370000000C.gz', '00000001000000370000000D',
- '00000001000000370000000E', '00000001000000370000000F.partial',);
+# WAL file patterns created before running each sub-scenario. "present"
+# tracks if the file with "name" still exists or not after running
+# pg_archivecleanup.
+my @walfiles_verbose = (
+ { name => '00000001000000370000000D', present => 0 },
+ { name => '00000001000000370000000E', present => 1 });
+my @walfiles_with_gz = (
+ { name => '00000001000000370000000C.gz', present => 0 },
+ { name => '00000001000000370000000D', present => 0 },
+ { name => '00000001000000370000000D.backup', present => 1 },
+ { name => '00000001000000370000000E', present => 1 },
+ { name => '00000001000000370000000F.partial', present => 1 },
+ { name => 'unrelated_file', present => 1 });
+my @walfiles_for_clean_backup_history = (
+ { name => '00000001000000370000000D', present => 0 },
+ { name => '00000001000000370000000D.00000028.backup', present => 0 },
+ { name => '00000001000000370000000E', present => 1 },
+ { name => '00000001000000370000000F.partial', present => 1 },
+ { name => 'unrelated_file', present => 1 });
sub create_files
{
- foreach my $fn (@walfiles, 'unrelated_file')
+ foreach my $fn (map { $_->{name} } @_)
{
open my $file, '>', "$tempdir/$fn";
+
print $file 'CONTENT';
close $file;
}
return;
}
-create_files();
+sub remove_files
+{
+ foreach my $fn (map { $_->{name} } @_)
+ {
+ unlink "$tempdir/$fn";
+ }
+ return;
+}
command_fails_like(
['pg_archivecleanup'],
@@ -54,54 +78,86 @@ command_fails_like(
qr/invalid file name argument/,
'fails with invalid restart file name');
+# Test a dry run, no files are physically removed, but logs are generated
+# to show what would be removed.
{
- # like command_like but checking stderr
+ create_files(@walfiles_verbose);
+
my $stderr;
+ my $oldestkeptwalfile = '00000001000000370000000E';
my $result =
IPC::Run::run [ 'pg_archivecleanup', '-d', '-n', $tempdir,
- $walfiles[2] ],
+ $oldestkeptwalfile ],
'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)
+
+ for my $walpair (@walfiles_verbose)
+ {
+ if ($walpair->{present})
+ {
+ unlike(
+ $stderr,
+ qr/$walpair->{name}.*would be removed/,
+ "pg_archivecleanup dry run for $walpair->{name}: matches");
+ }
+ else
+ {
+ like(
+ $stderr,
+ qr/$walpair->{name}.*would be removed/,
+ "pg_archivecleanup dry run for $walpair->{name}: matches");
+ }
+ }
+ foreach my $fn (map { $_->{name} } @walfiles_verbose)
{
ok(-f "$tempdir/$fn", "$fn not removed");
}
+
+ remove_files(@walfiles_verbose);
}
sub run_check
{
local $Test::Builder::Level = $Test::Builder::Level + 1;
- my ($suffix, $test_name) = @_;
+ my ($testdata, $oldestkeptwalfile, $test_name, @options) = @_;
- create_files();
+ create_files(@$testdata);
command_ok(
- [
- 'pg_archivecleanup', '-x', '.gz', $tempdir,
- $walfiles[2] . $suffix
- ],
+ [ 'pg_archivecleanup', @options, $tempdir, $oldestkeptwalfile ],
"$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");
+ for my $walpair (@$testdata)
+ {
+ if ($walpair->{present})
+ {
+ ok(-f "$tempdir/$walpair->{name}",
+ "$test_name:$walpair->{name} was not cleaned up");
+ }
+ else
+ {
+ ok(!-f "$tempdir/$walpair->{name}",
+ "$test_name:$walpair->{name} was cleaned up");
+ }
+ }
+
+ remove_files(@$testdata);
return;
}
-run_check('', 'pg_archivecleanup');
-run_check('.partial', 'pg_archivecleanup with .partial file');
-run_check('.00000020.backup', 'pg_archivecleanup with .backup file');
+run_check(\@walfiles_with_gz, '00000001000000370000000E',
+ 'pg_archivecleanup', '-x.gz');
+run_check(
+ \@walfiles_with_gz,
+ '00000001000000370000000E.partial',
+ 'pg_archivecleanup with .partial file', '-x.gz');
+run_check(
+ \@walfiles_with_gz,
+ '00000001000000370000000E.00000020.backup',
+ 'pg_archivecleanup with .backup file', '-x.gz');
+run_check(\@walfiles_for_clean_backup_history,
+ '00000001000000370000000E',
+ 'pg_archivecleanup with --clean-backup-history', '-b');
done_testing();