@@ -868,47 +868,132 @@ pgBackupGetPath2(const pgBackup *backup, char *path, size_t len,
868
868
make_native_path (path );
869
869
}
870
870
871
- /* Find parent base FULL backup for current backup using parent_backup_link,
872
- * return NULL if not found
871
+ /*
872
+ * Find parent base FULL backup for current backup using parent_backup_link
873
873
*/
874
874
pgBackup *
875
- find_parent_backup (pgBackup * current_backup )
875
+ find_parent_full_backup (pgBackup * current_backup )
876
876
{
877
877
pgBackup * base_full_backup = NULL ;
878
878
base_full_backup = current_backup ;
879
879
880
- while (base_full_backup -> backup_mode != BACKUP_MODE_FULL )
880
+ if (!current_backup )
881
+ elog (ERROR , "Target backup cannot be NULL" );
882
+
883
+ while (base_full_backup -> parent_backup_link != NULL )
881
884
{
882
- /*
883
- * If we haven't found parent for incremental backup,
884
- * mark it and all depending backups as orphaned
885
- */
886
- if (base_full_backup -> parent_backup_link == NULL
887
- || (base_full_backup -> status != BACKUP_STATUS_OK
888
- && base_full_backup -> status != BACKUP_STATUS_DONE ))
889
- {
890
- pgBackup * orphaned_backup = current_backup ;
885
+ base_full_backup = base_full_backup -> parent_backup_link ;
886
+ }
891
887
892
- while (orphaned_backup != NULL )
893
- {
894
- orphaned_backup -> status = BACKUP_STATUS_ORPHAN ;
895
- pgBackupWriteBackupControlFile (orphaned_backup );
896
- if (base_full_backup -> parent_backup_link == NULL )
897
- elog (WARNING , "Backup %s is orphaned because its parent backup is not found" ,
898
- base36enc (orphaned_backup -> start_time ));
899
- else
900
- elog (WARNING , "Backup %s is orphaned because its parent backup is corrupted" ,
901
- base36enc (orphaned_backup -> start_time ));
902
-
903
- orphaned_backup = orphaned_backup -> parent_backup_link ;
904
- }
888
+ if (base_full_backup -> backup_mode != BACKUP_MODE_FULL )
889
+ elog (ERROR , "Failed to find FULL backup parent for %s" ,
890
+ base36enc (current_backup -> start_time ));
905
891
906
- base_full_backup = NULL ;
907
- break ;
908
- }
892
+ return base_full_backup ;
893
+ }
909
894
910
- base_full_backup = base_full_backup -> parent_backup_link ;
895
+ /*
896
+ * Interate over parent chain and look for any problems.
897
+ * Return 0 if chain is broken.
898
+ * result_backup must contain oldest existing backup after missing backup.
899
+ * we have no way to know if there is multiple missing backups.
900
+ * Return 1 if chain is intact, but some backup is !OK.
901
+ * result_backup must contain oldest !OK backup.
902
+ * Return 2 if chain is intact and all backup are OK.
903
+ * result_backup must contain FULL backup on which chain is based.
904
+ */
905
+ int
906
+ scan_parent_chain (pgBackup * current_backup , pgBackup * * result_backup )
907
+ {
908
+ pgBackup * target_backup = NULL ;
909
+ pgBackup * invalid_backup = NULL ;
910
+
911
+ if (!current_backup )
912
+ elog (ERROR , "Target backup cannot be NULL" );
913
+
914
+ target_backup = current_backup ;
915
+
916
+ while (target_backup -> parent_backup_link )
917
+ {
918
+ if (target_backup -> status != BACKUP_STATUS_OK &&
919
+ target_backup -> status != BACKUP_STATUS_DONE )
920
+ /* oldest invalid backup in parent chain */
921
+ invalid_backup = target_backup ;
922
+
923
+
924
+ target_backup = target_backup -> parent_backup_link ;
911
925
}
912
926
913
- return base_full_backup ;
927
+ /* Prevous loop will skip FULL backup because his parent_backup_link is NULL */
928
+ if (target_backup -> backup_mode == BACKUP_MODE_FULL &&
929
+ (target_backup -> status != BACKUP_STATUS_OK &&
930
+ target_backup -> status != BACKUP_STATUS_DONE ))
931
+ {
932
+ invalid_backup = target_backup ;
933
+ }
934
+
935
+ /* found chain end and oldest backup is not FULL */
936
+ if (target_backup -> backup_mode != BACKUP_MODE_FULL )
937
+ {
938
+ /* Set oldest child backup in chain */
939
+ * result_backup = target_backup ;
940
+ return 0 ;
941
+ }
942
+
943
+ /* chain is ok, but some backups are invalid */
944
+ if (invalid_backup )
945
+ {
946
+ * result_backup = invalid_backup ;
947
+ return 1 ;
948
+ }
949
+
950
+ * result_backup = target_backup ;
951
+ return 2 ;
952
+ }
953
+
954
+ /*
955
+ * Determine if child_backup descend from parent_backup
956
+ * This check DO NOT(!!!) guarantee that parent chain is intact, because parent_backup
957
+ * can be missing.
958
+ * If inclusive is true, then full backup counts as a child of himself.
959
+ */
960
+ bool
961
+ is_parent (time_t parent_backup_time , pgBackup * child_backup , bool inclusive )
962
+ {
963
+ if (!child_backup )
964
+ elog (ERROR , "Target backup cannot be NULL" );
965
+
966
+ while (child_backup -> parent_backup_link &&
967
+ child_backup -> parent_backup != parent_backup_time )
968
+ {
969
+ child_backup = child_backup -> parent_backup_link ;
970
+ }
971
+
972
+ if (child_backup -> parent_backup == parent_backup_time )
973
+ return true;
974
+
975
+ if (inclusive && child_backup -> start_time == parent_backup_time )
976
+ return true;
977
+
978
+ return false;
979
+ }
980
+
981
+ /*
982
+ * return backup index number.
983
+ * Note: this index number holds true until new sorting of backup list
984
+ */
985
+ int
986
+ get_backup_index_number (parray * backup_list , pgBackup * backup )
987
+ {
988
+ int i ;
989
+
990
+ for (i = 0 ; i < parray_num (backup_list ); i ++ )
991
+ {
992
+ pgBackup * tmp_backup = (pgBackup * ) parray_get (backup_list , i );
993
+
994
+ if (tmp_backup -> start_time == backup -> start_time )
995
+ return i ;
996
+ }
997
+ elog (ERROR , "Failed to find backup %s" , base36enc (backup -> start_time ));
998
+ return 0 ;
914
999
}
0 commit comments