Skip to content

Commit cc42c55

Browse files
committed
PGPRO-428: validation and revalidation rework based on parent_backup_link
1 parent 26bd9cf commit cc42c55

File tree

5 files changed

+1955
-317
lines changed

5 files changed

+1955
-317
lines changed

src/catalog.c

Lines changed: 116 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -868,47 +868,132 @@ pgBackupGetPath2(const pgBackup *backup, char *path, size_t len,
868868
make_native_path(path);
869869
}
870870

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
873873
*/
874874
pgBackup*
875-
find_parent_backup(pgBackup *current_backup)
875+
find_parent_full_backup(pgBackup *current_backup)
876876
{
877877
pgBackup *base_full_backup = NULL;
878878
base_full_backup = current_backup;
879879

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)
881884
{
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+
}
891887

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));
905891

906-
base_full_backup = NULL;
907-
break;
908-
}
892+
return base_full_backup;
893+
}
909894

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;
911925
}
912926

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;
914999
}

src/pg_probackup.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,10 @@ extern void pgBackupFree(void *backup);
487487
extern int pgBackupCompareId(const void *f1, const void *f2);
488488
extern int pgBackupCompareIdDesc(const void *f1, const void *f2);
489489

490-
extern pgBackup* find_parent_backup(pgBackup *current_backup);
490+
extern pgBackup* find_parent_full_backup(pgBackup *current_backup);
491+
extern int scan_parent_chain(pgBackup *current_backup, pgBackup **result_backup);
492+
extern bool is_parent(time_t parent_backup_time, pgBackup *child_backup, bool inclusive);
493+
extern int get_backup_index_number(parray *backup_list, pgBackup *backup);
491494

492495
/* in dir.c */
493496
extern void dir_list_file(parray *files, const char *root, bool exclude,

0 commit comments

Comments
 (0)