pg_archivecleanup: Refactor loop doing old segment removals

This commit refactors a bit the main loop of pg_archivecleanup that
handles the removal of old segments, reducing by one its level of
indentation.  This will help an incoming patch that adds a new option
related to the segment filtering logic.

Author: Atsushi Torikoshi
Reviewed-by: Kyotaro Horiguchi, Fujii Masao, Michael Paquier
Discussion: https://postgr.es/m/d660ef741ce3d82f3b4283f1cafd576c@oss.nttdata.com
This commit is contained in:
Michael Paquier 2023-07-19 12:23:53 +09:00
parent 961cf5c905
commit 4a7556f77c
1 changed files with 66 additions and 62 deletions

View File

@ -93,75 +93,79 @@ CleanupPriorWALFiles(void)
struct dirent *xlde;
char walfile[MAXPGPATH];
if ((xldir = opendir(archiveLocation)) != NULL)
xldir = opendir(archiveLocation);
if (xldir == NULL)
pg_fatal("could not open archive location \"%s\": %m",
archiveLocation);
while (errno = 0, (xlde = readdir(xldir)) != NULL)
{
while (errno = 0, (xlde = readdir(xldir)) != NULL)
char WALFilePath[MAXPGPATH * 2]; /* the file path including
* 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.)
*/
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.
*/
if (!IsXLogFileName(walfile) && !IsPartialXLogFileName(walfile))
continue;
/*
* 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 (strcmp(walfile + 8, exclusiveCleanupFileName + 8) >= 0)
continue;
/*
* 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)
{
/*
* 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.)
* 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.
*/
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_fatal("could not remove file \"%s\": %m",
WALFilePath);
}
printf("%s\n", WALFilePath);
pg_log_debug("file \"%s\" would be removed", WALFilePath);
continue;
}
if (errno)
pg_fatal("could not read archive location \"%s\": %m",
archiveLocation);
if (closedir(xldir))
pg_fatal("could not close archive location \"%s\": %m",
archiveLocation);
pg_log_debug("removing file \"%s\"", WALFilePath);
rc = unlink(WALFilePath);
if (rc != 0)
pg_fatal("could not remove file \"%s\": %m",
WALFilePath);
}
else
pg_fatal("could not open archive location \"%s\": %m",
if (errno)
pg_fatal("could not read archive location \"%s\": %m",
archiveLocation);
if (closedir(xldir))
pg_fatal("could not close archive location \"%s\": %m",
archiveLocation);
}