From 4a7556f77c44d295241d2432094b40156f69be1a Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 19 Jul 2023 12:23:53 +0900 Subject: [PATCH] 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 --- src/bin/pg_archivecleanup/pg_archivecleanup.c | 128 +++++++++--------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/src/bin/pg_archivecleanup/pg_archivecleanup.c b/src/bin/pg_archivecleanup/pg_archivecleanup.c index fc0dca9856..3533c9b1ab 100644 --- a/src/bin/pg_archivecleanup/pg_archivecleanup.c +++ b/src/bin/pg_archivecleanup/pg_archivecleanup.c @@ -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); }