14
14
#include <time.h>
15
15
#include <unistd.h>
16
16
17
- static void delete_walfiles (XLogRecPtr keep_lsn , timelineInfo * tli ,
17
+ static void delete_walfiles_in_tli (XLogRecPtr keep_lsn , timelineInfo * tli ,
18
18
uint32 xlog_seg_size , bool dry_run );
19
19
static void do_retention_internal (parray * backup_list , parray * to_keep_list ,
20
20
parray * to_purge_list );
@@ -607,10 +607,11 @@ do_retention_purge(parray *to_keep_list, parray *to_purge_list)
607
607
}
608
608
}
609
609
610
- /* Purge WAL
610
+ /*
611
+ * Purge WAL
611
612
* 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.
614
615
*/
615
616
static void
616
617
do_retention_wal (bool dry_run )
@@ -624,25 +625,32 @@ do_retention_wal(bool dry_run)
624
625
{
625
626
timelineInfo * tlinfo = (timelineInfo * ) parray_get (tli_list , i );
626
627
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 )
630
633
continue ;
631
634
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
+ */
633
639
if (tlinfo -> closest_backup )
634
640
continue ;
635
641
636
642
/*
637
643
* 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
639
645
* can be safely purged.
646
+ * Note, that oldest_backup is not necessarily valid here,
647
+ * but still we keep wal for it.
640
648
*/
641
649
if (tlinfo -> oldest_backup )
642
- delete_walfiles (tlinfo -> oldest_backup -> start_lsn ,
650
+ delete_walfiles_in_tli (tlinfo -> oldest_backup -> start_lsn ,
643
651
tlinfo , instance_config .xlog_seg_size , dry_run );
644
652
else
645
- delete_walfiles (InvalidXLogRecPtr ,
653
+ delete_walfiles_in_tli (InvalidXLogRecPtr ,
646
654
tlinfo , instance_config .xlog_seg_size , dry_run );
647
655
}
648
656
}
@@ -710,7 +718,8 @@ delete_backup_files(pgBackup *backup)
710
718
return ;
711
719
}
712
720
713
- /* Purge WAL archive.
721
+ /*
722
+ * Purge WAL archive. One timeline at a time.
714
723
* If 'keep_lsn' is InvalidXLogRecPtr, then whole timeline can be purged
715
724
* If 'keep_lsn' is valid LSN, then every lesser segment can be purged.
716
725
* If 'dry_run' is set, then don`t actually delete anything.
@@ -720,7 +729,8 @@ delete_backup_files(pgBackup *backup)
720
729
* Case 2:
721
730
* archive is not empty, 'keep_lsn' is valid and prevening us from deleting anything.
722
731
* 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.
724
734
* Case 4:
725
735
* archive is empty, 'keep_lsn' is valid, assume corruption of WAL archive.
726
736
* Case 5:
@@ -730,11 +740,11 @@ delete_backup_files(pgBackup *backup)
730
740
* Q: Maybe we should stop treating partial WAL segments as second-class citizens?
731
741
*/
732
742
static void
733
- delete_walfiles (XLogRecPtr keep_lsn , timelineInfo * tlinfo ,
743
+ delete_walfiles_in_tli (XLogRecPtr keep_lsn , timelineInfo * tlinfo ,
734
744
uint32 xlog_seg_size , bool dry_run )
735
745
{
736
- XLogSegNo StartSegNo ; /* First segment to delete */
737
- XLogSegNo EndSegNo = 0 ; /* Oldest segment to keep */
746
+ XLogSegNo FirstToDeleteSegNo ;
747
+ XLogSegNo OldestToKeepSegNo = 0 ;
738
748
int rc ;
739
749
int i ;
740
750
int wal_size_logical = 0 ;
@@ -752,47 +762,47 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
752
762
if (XLogRecPtrIsInvalid (keep_lsn ))
753
763
{
754
764
/* 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 ;
758
769
purge_all = true;
759
770
}
760
771
else
761
772
{
762
773
/* 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 );
765
776
}
766
777
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" );
773
784
774
785
/* 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 )
779
789
{
780
- /* It is actually possible for EndSegNo to be less than StartSegNo
790
+ /* It is actually possible for OldestToKeepSegNo to be less than FirstToDeleteSegNo
781
791
* in case of :
782
792
* 1. WAL archive corruption.
783
793
* 2. There is no actual WAL archive to speak of and
784
794
* 'keep_lsn' is coming from STREAM backup.
785
795
*
786
796
* Assume the worst.
787
797
*/
788
- if (StartSegNo > 0 && EndSegNo > 0 )
798
+ if (FirstToDeleteSegNo > 0 && OldestToKeepSegNo > 0 )
789
799
elog (WARNING , "On timeline %i first segment %08X%08X is greater than "
790
800
"oldest segment to keep %08X%08X. Possible WAL archive corruption!" ,
791
801
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 );
794
804
}
795
- else if (EndSegNo == StartSegNo && !purge_all )
805
+ else if (OldestToKeepSegNo == FirstToDeleteSegNo && !purge_all )
796
806
{
797
807
/* 'Nothing to delete' scenario because of 'keep_lsn'
798
808
* with possible exception of partial and backup history files.
@@ -804,7 +814,7 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
804
814
if (wal_size_logical > 0 )
805
815
{
806
816
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" ,
808
818
tlinfo -> tli , wal_pretty_size );
809
819
}
810
820
@@ -813,15 +823,15 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
813
823
{
814
824
xlogFile * wal_file = (xlogFile * ) parray_get (tlinfo -> xlog_filelist , i );
815
825
816
- if (purge_all || wal_file -> segno < EndSegNo )
826
+ if (purge_all || wal_file -> segno < OldestToKeepSegNo )
817
827
wal_size_actual += wal_file -> file .size ;
818
828
}
819
829
820
830
/* Report the actual size to delete */
821
831
if (wal_size_actual > 0 )
822
832
{
823
833
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" ,
825
835
tlinfo -> tli , wal_pretty_size );
826
836
}
827
837
@@ -838,7 +848,7 @@ delete_walfiles(XLogRecPtr keep_lsn, timelineInfo *tlinfo,
838
848
/* Any segment equal or greater than EndSegNo must be kept
839
849
* unless it`s a 'purge all' scenario.
840
850
*/
841
- if (purge_all || wal_file -> segno < EndSegNo )
851
+ if (purge_all || wal_file -> segno < OldestToKeepSegNo )
842
852
{
843
853
/* unlink segment */
844
854
rc = unlink (wal_file -> file .path );
0 commit comments