Skip to content

Commit

Permalink
pg_archivecleanup: Refactor loop doing old segment removals
Browse files Browse the repository at this point in the history
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
  • Loading branch information
michaelpq committed Jul 19, 2023
1 parent 961cf5c commit 4a7556f
Showing 1 changed file with 66 additions and 62 deletions.
128 changes: 66 additions & 62 deletions src/bin/pg_archivecleanup/pg_archivecleanup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit 4a7556f

Please sign in to comment.