Skip to content

Commit 1f67593

Browse files
committed
code cleanup for wal_delete refactoring
1 parent c9d3c58 commit 1f67593

File tree

2 files changed

+106
-111
lines changed

2 files changed

+106
-111
lines changed

src/catalog.c

Lines changed: 56 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include "utils/file.h"
2020
#include "utils/configuration.h"
2121

22-
static pgBackup* get_closest_backup(timelineInfo *tlinfo, parray *backup_list);
23-
static pgBackup* get_oldest_backup(timelineInfo *tlinfo, parray *backup_list);
22+
static pgBackup* get_closest_backup(timelineInfo *tlinfo);
23+
static pgBackup* get_oldest_backup(timelineInfo *tlinfo);
2424
static const char *backupModes[] = {"", "PAGE", "PTRACK", "DELTA", "FULL"};
2525
static pgBackup *readBackupControlFile(const char *path);
2626

@@ -891,111 +891,96 @@ catalog_get_timelines(InstanceConfig *instance)
891891
{
892892
timelineInfo *tlinfo = parray_get(timelineinfos, i);
893893

894-
tlinfo->oldest_backup = get_oldest_backup(tlinfo, backups);
895-
tlinfo->closest_backup = get_closest_backup(tlinfo, backups);
894+
tlinfo->oldest_backup = get_oldest_backup(tlinfo);
895+
tlinfo->closest_backup = get_closest_backup(tlinfo);
896896
}
897897

898-
//parray_walk(xlog_files_list, pfree);
899-
//parray_free(xlog_files_list);
900-
901898
return timelineinfos;
902899
}
903900

904901
/*
905-
* Iterate over parent timelines of a given timeline and look
906-
* for valid backup closest to given timeline switchpoint.
902+
* Iterate over parent timelines and look for valid backup
903+
* closest to given timeline switchpoint.
907904
*
908-
* Returns NULL if such backup is not found.
905+
* If such backup doesn't exist, it means that
906+
* timeline is unreachable. Return NULL.
909907
*/
910908
pgBackup*
911-
get_closest_backup(timelineInfo *tlinfo, parray *backup_list)
909+
get_closest_backup(timelineInfo *tlinfo)
912910
{
913911
pgBackup *closest_backup = NULL;
914912
int i;
915913

916-
/* Only timeline with switchpoint can possibly have closest backup */
917-
if (XLogRecPtrIsInvalid(tlinfo->switchpoint))
918-
return NULL;
919-
920-
/* Only timeline with parent timeline can possibly have closest backup */
921-
if (!tlinfo->parent_link)
922-
return NULL;
923-
924-
while (tlinfo->parent_link)
914+
/*
915+
* Iterate over backups belonging to parent timelines
916+
* and look for candidates.
917+
*/
918+
while (tlinfo->parent_link && !closest_backup)
925919
{
926-
/*
927-
* Iterate over backups belonging to parent timeline and look
928-
* for candidates.
929-
*/
930-
for (i = 0; i < parray_num(backup_list); i++)
920+
parray *backup_list = tlinfo->parent_link->backups;
921+
if (backup_list != NULL)
931922
{
932-
pgBackup *backup = parray_get(backup_list, i);
933-
934-
/* Backups belonging to timelines other than parent timeline can be safely skipped */
935-
if (backup->tli != tlinfo->parent_tli)
936-
continue;
937-
938-
/* Backups in future can be safely skipped */
939-
if (backup->stop_lsn > tlinfo->switchpoint)
940-
continue;
941-
942-
/* Backups with invalid STOP LSN can be safely skipped */
943-
if (XLogRecPtrIsInvalid(backup->stop_lsn) ||
944-
!XRecOffIsValid(backup->stop_lsn))
945-
continue;
946-
947-
/* Only valid backups closest to switchpoint should be considered */
948-
if (backup->stop_lsn <= tlinfo->switchpoint &&
949-
(backup->status == BACKUP_STATUS_OK ||
950-
backup->status == BACKUP_STATUS_DONE))
923+
for (i = 0; i < parray_num(backup_list); i++)
951924
{
952-
/* Check if backup is closer to switchpoint than current candidate */
953-
if (!closest_backup || backup->stop_lsn > closest_backup->stop_lsn)
954-
closest_backup = backup;
925+
pgBackup *backup = parray_get(backup_list, i);
926+
927+
/*
928+
* Only valid backups made before switchpoint
929+
* should be considered.
930+
*/
931+
if (!XLogRecPtrIsInvalid(backup->stop_lsn) &&
932+
!XRecOffIsValid(backup->stop_lsn) &&
933+
backup->stop_lsn <= tlinfo->switchpoint &&
934+
(backup->status == BACKUP_STATUS_OK ||
935+
backup->status == BACKUP_STATUS_DONE))
936+
{
937+
/* Check if backup is closer to switchpoint than current candidate */
938+
if (!closest_backup || backup->stop_lsn > closest_backup->stop_lsn)
939+
closest_backup = backup;
940+
}
955941
}
956942
}
957943

958-
/* Closest backup is found */
959-
if (closest_backup)
960-
break;
961-
962-
/* Switch to parent */
944+
/* Continue with parent */
963945
tlinfo = tlinfo->parent_link;
964946
}
965947

966948
return closest_backup;
967949
}
968950

969951
/*
970-
* Iterate over timelines and look for oldest backup on each timeline
952+
* Find oldest backup in given timeline
953+
* to determine what WAL segments belonging to this timeline,
954+
* are not reachable from any backup.
955+
*
971956
* Returns NULL if such backup is not found.
972957
*/
973958
pgBackup*
974-
get_oldest_backup(timelineInfo *tlinfo, parray *backup_list)
959+
get_oldest_backup(timelineInfo *tlinfo)
975960
{
976961
pgBackup *oldest_backup = NULL;
977962
int i;
963+
parray *backup_list = tlinfo->backups;
978964

979-
/*
980-
* Iterate over backups belonging to timeline and look
981-
* for candidates.
982-
*/
983-
for (i = 0; i < parray_num(backup_list); i++)
965+
if (backup_list != NULL)
984966
{
985-
pgBackup *backup = parray_get(backup_list, i);
986-
987-
/* Backups belonging to other timelines can be safely skipped */
988-
if (backup->tli != tlinfo->tli)
989-
continue;
967+
for (i = 0; i < parray_num(backup_list); i++)
968+
{
969+
pgBackup *backup = parray_get(backup_list, i);
990970

991-
/* Backups with invalid START LSN can be safely skipped */
992-
if (XLogRecPtrIsInvalid(backup->start_lsn) ||
993-
!XRecOffIsValid(backup->start_lsn))
994-
continue;
971+
/* Backups with invalid START LSN can be safely skipped */
972+
if (XLogRecPtrIsInvalid(backup->start_lsn) ||
973+
!XRecOffIsValid(backup->start_lsn))
974+
continue;
995975

996-
/* Check if backup is older than current candidate */
997-
if (!oldest_backup || backup->start_lsn < oldest_backup->start_lsn)
998-
oldest_backup = backup;
976+
/*
977+
* Check if backup is older than current candidate.
978+
* Here we use start_lsn for comparison, because backup that
979+
* started earlier needs more WAL.
980+
*/
981+
if (!oldest_backup || backup->start_lsn < oldest_backup->start_lsn)
982+
oldest_backup = backup;
983+
}
999984
}
1000985

1001986
return oldest_backup;

src/delete.c

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <time.h>
1515
#include <unistd.h>
1616

17-
static void delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tli,
17+
static void delete_walfiles_in_tli(XLogRecPtr keep_lsn, timelineInfo *tli,
1818
uint32 xlog_seg_size, bool dry_run);
1919
static void do_retention_internal(parray *backup_list, parray *to_keep_list,
2020
parray *to_purge_list);
@@ -607,10 +607,11 @@ do_retention_purge(parray *to_keep_list, parray *to_purge_list)
607607
}
608608
}
609609

610-
/* Purge WAL
610+
/*
611+
* Purge WAL
611612
* Iterate over timelines
612-
* Look for closest_backup, if exists, goto next timelime
613-
* if not exists, look for oldest backup on timeline
613+
* Look for WAL segment not reachable from existing backups
614+
* and delete them.
614615
*/
615616
static void
616617
do_retention_wal(bool dry_run)
@@ -624,25 +625,32 @@ do_retention_wal(bool dry_run)
624625
{
625626
timelineInfo *tlinfo = (timelineInfo *) parray_get(tli_list, i);
626627

627-
/* Empty timeline can be safely skipped */
628-
if (tlinfo->n_xlog_files == 0 &&
629-
parray_num(tlinfo->xlog_filelist) == 0)
628+
/*
629+
* Empty timeline (only mentioned in timeline history file)
630+
* has nothing to cleanup.
631+
*/
632+
if (tlinfo->n_xlog_files == 0 && parray_num(tlinfo->xlog_filelist) == 0)
630633
continue;
631634

632-
/* If closest backup is exists, then timeline can be safely skipped */
635+
/*
636+
* If closest backup exists, then timeline is reachable from
637+
* at least one backup and none files should not be removed.
638+
*/
633639
if (tlinfo->closest_backup)
634640
continue;
635641

636642
/*
637643
* Purge all WAL segments before START LSN of oldest backup.
638-
* If there is no backups on timeline, then whole timeline
644+
* If timeline doesn't have a backup, then whole timeline
639645
* can be safely purged.
646+
* Note, that oldest_backup is not necessarily valid here,
647+
* but still we keep wal for it.
640648
*/
641649
if (tlinfo->oldest_backup)
642-
delete_walfiles(tlinfo->oldest_backup->start_lsn,
650+
delete_walfiles_in_tli(tlinfo->oldest_backup->start_lsn,
643651
tlinfo, instance_config.xlog_seg_size, dry_run);
644652
else
645-
delete_walfiles(InvalidXLogRecPtr,
653+
delete_walfiles_in_tli(InvalidXLogRecPtr,
646654
tlinfo, instance_config.xlog_seg_size, dry_run);
647655
}
648656
}
@@ -710,7 +718,8 @@ delete_backup_files(pgBackup *backup)
710718
return;
711719
}
712720

713-
/* Purge WAL archive.
721+
/*
722+
* Purge WAL archive. One timeline at a time.
714723
* If 'keep_lsn' is InvalidXLogRecPtr, then whole timeline can be purged
715724
* If 'keep_lsn' is valid LSN, then every lesser segment can be purged.
716725
* If 'dry_run' is set, then don`t actually delete anything.
@@ -720,7 +729,8 @@ delete_backup_files(pgBackup *backup)
720729
* Case 2:
721730
* archive is not empty, 'keep_lsn' is valid and prevening us from deleting anything.
722731
* Case 3:
723-
* archive is not empty, 'keep_lsn' is invalid, drop everyhing in archive.
732+
* archive is not empty, 'keep_lsn' is invalid, drop all WAL files in archive,
733+
* belonging to the timeline.
724734
* Case 4:
725735
* archive is empty, 'keep_lsn' is valid, assume corruption of WAL archive.
726736
* Case 5:
@@ -730,11 +740,11 @@ delete_backup_files(pgBackup *backup)
730740
* Q: Maybe we should stop treating partial WAL segments as second-class citizens?
731741
*/
732742
static void
733-
delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
743+
delete_walfiles_in_tli(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
734744
uint32 xlog_seg_size, bool dry_run)
735745
{
736-
XLogSegNo StartSegNo; /* First segment to delete */
737-
XLogSegNo EndSegNo = 0; /* Oldest segment to keep */
746+
XLogSegNo FirstToDeleteSegNo;
747+
XLogSegNo OldestToKeepSegNo = 0;
738748
int rc;
739749
int i;
740750
int wal_size_logical = 0;
@@ -752,47 +762,47 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
752762
if (XLogRecPtrIsInvalid(keep_lsn))
753763
{
754764
/* Drop all files in timeline */
755-
elog(INFO, "All files on timeline %i will be removed", tlinfo->tli);
756-
StartSegNo = tlinfo->begin_segno;
757-
EndSegNo = tlinfo->end_segno;
765+
elog(INFO, "All files on timeline %i %s be removed", tlinfo->tli,
766+
dry_run?"can":"will");
767+
FirstToDeleteSegNo = tlinfo->begin_segno;
768+
OldestToKeepSegNo = tlinfo->end_segno;
758769
purge_all = true;
759770
}
760771
else
761772
{
762773
/* Drop all segments between begin_segno and segment with keep_lsn (excluding) */
763-
StartSegNo = tlinfo->begin_segno;
764-
GetXLogSegNo(keep_lsn, EndSegNo, xlog_seg_size);
774+
FirstToDeleteSegNo = tlinfo->begin_segno;
775+
GetXLogSegNo(keep_lsn, OldestToKeepSegNo, xlog_seg_size);
765776
}
766777

767-
if (EndSegNo > 0 && EndSegNo > StartSegNo)
768-
elog(INFO, "WAL segments between %08X%08X and %08X%08X on timeline %i will be removed",
769-
(uint32) StartSegNo / xlog_seg_size, (uint32) StartSegNo % xlog_seg_size,
770-
(uint32) (EndSegNo - 1) / xlog_seg_size,
771-
(uint32) (EndSegNo - 1) % xlog_seg_size,
772-
tlinfo->tli);
778+
if (OldestToKeepSegNo > 0 && OldestToKeepSegNo > FirstToDeleteSegNo)
779+
elog(INFO, "WAL segments between %08X%08X and %08X%08X on timeline %i %s be removed",
780+
(uint32) FirstToDeleteSegNo / xlog_seg_size, (uint32) FirstToDeleteSegNo % xlog_seg_size,
781+
(uint32) (OldestToKeepSegNo - 1) / xlog_seg_size,
782+
(uint32) (OldestToKeepSegNo - 1) % xlog_seg_size,
783+
tlinfo->tli, dry_run?"can":"will");
773784

774785
/* sanity */
775-
if (EndSegNo > StartSegNo)
776-
/* typical scenario */
777-
wal_size_logical = (EndSegNo-StartSegNo) * xlog_seg_size;
778-
else if (EndSegNo < StartSegNo)
786+
if (OldestToKeepSegNo > FirstToDeleteSegNo)
787+
wal_size_logical = (OldestToKeepSegNo - FirstToDeleteSegNo) * xlog_seg_size;
788+
else if (OldestToKeepSegNo < FirstToDeleteSegNo)
779789
{
780-
/* It is actually possible for EndSegNo to be less than StartSegNo
790+
/* It is actually possible for OldestToKeepSegNo to be less than FirstToDeleteSegNo
781791
* in case of :
782792
* 1. WAL archive corruption.
783793
* 2. There is no actual WAL archive to speak of and
784794
* 'keep_lsn' is coming from STREAM backup.
785795
*
786796
* Assume the worst.
787797
*/
788-
if (StartSegNo > 0 && EndSegNo > 0)
798+
if (FirstToDeleteSegNo > 0 && OldestToKeepSegNo > 0)
789799
elog(WARNING, "On timeline %i first segment %08X%08X is greater than "
790800
"oldest segment to keep %08X%08X. Possible WAL archive corruption!",
791801
tlinfo->tli,
792-
(uint32) StartSegNo / xlog_seg_size, (uint32) StartSegNo % xlog_seg_size,
793-
(uint32) EndSegNo / xlog_seg_size, (uint32) EndSegNo % xlog_seg_size);
802+
(uint32) FirstToDeleteSegNo / xlog_seg_size, (uint32) FirstToDeleteSegNo % xlog_seg_size,
803+
(uint32) OldestToKeepSegNo / xlog_seg_size, (uint32) OldestToKeepSegNo % xlog_seg_size);
794804
}
795-
else if (EndSegNo == StartSegNo && !purge_all)
805+
else if (OldestToKeepSegNo == FirstToDeleteSegNo && !purge_all)
796806
{
797807
/* 'Nothing to delete' scenario because of 'keep_lsn'
798808
* with possible exception of partial and backup history files.
@@ -804,7 +814,7 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
804814
if (wal_size_logical > 0)
805815
{
806816
pretty_size(wal_size_logical, wal_pretty_size, lengthof(wal_pretty_size));
807-
elog(INFO, "WAL size to remove on timeline %i: %s",
817+
elog(INFO, "Logical WAL size to remove on timeline %i : %s",
808818
tlinfo->tli, wal_pretty_size);
809819
}
810820

@@ -813,15 +823,15 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
813823
{
814824
xlogFile *wal_file = (xlogFile *) parray_get(tlinfo->xlog_filelist, i);
815825

816-
if (purge_all || wal_file->segno < EndSegNo)
826+
if (purge_all || wal_file->segno < OldestToKeepSegNo)
817827
wal_size_actual += wal_file->file.size;
818828
}
819829

820830
/* Report the actual size to delete */
821831
if (wal_size_actual > 0)
822832
{
823833
pretty_size(wal_size_actual, wal_pretty_size, lengthof(wal_pretty_size));
824-
elog(INFO, "Resident data size to free on timeline %i: %s",
834+
elog(INFO, "Resident data size to free on timeline %i : %s",
825835
tlinfo->tli, wal_pretty_size);
826836
}
827837

@@ -838,7 +848,7 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
838848
/* Any segment equal or greater than EndSegNo must be kept
839849
* unless it`s a 'purge all' scenario.
840850
*/
841-
if (purge_all || wal_file->segno < EndSegNo)
851+
if (purge_all || wal_file->segno < OldestToKeepSegNo)
842852
{
843853
/* unlink segment */
844854
rc = unlink(wal_file->file.path);

0 commit comments

Comments
 (0)