Skip to content

Commit 264cd18

Browse files
committed
check links to parent backup in validate
1 parent e71312c commit 264cd18

File tree

4 files changed

+87
-52
lines changed

4 files changed

+87
-52
lines changed

src/catalog.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,3 +714,48 @@ pgBackupGetPath2(const pgBackup *backup, char *path, size_t len,
714714

715715
make_native_path(path);
716716
}
717+
718+
/* Find parent base FULL backup for current backup using parent_backup_link,
719+
* return NULL if not found
720+
*/
721+
pgBackup*
722+
find_parent_backup(pgBackup *current_backup)
723+
{
724+
pgBackup *base_full_backup = NULL;
725+
base_full_backup = current_backup;
726+
727+
while (base_full_backup->backup_mode != BACKUP_MODE_FULL)
728+
{
729+
/*
730+
* If we haven't found parent for incremental backup,
731+
* mark it and all depending backups as orphaned
732+
*/
733+
if (base_full_backup->parent_backup_link == NULL
734+
|| (base_full_backup->status != BACKUP_STATUS_OK
735+
&& base_full_backup->status != BACKUP_STATUS_DONE))
736+
{
737+
pgBackup *orphaned_backup = current_backup;
738+
739+
while (orphaned_backup != NULL)
740+
{
741+
orphaned_backup->status = BACKUP_STATUS_ORPHAN;
742+
pgBackupWriteBackupControlFile(orphaned_backup);
743+
if (base_full_backup->parent_backup_link == NULL)
744+
elog(WARNING, "Backup %s is orphaned because its parent backup is not found",
745+
base36enc(orphaned_backup->start_time));
746+
else
747+
elog(WARNING, "Backup %s is orphaned because its parent backup is corrupted",
748+
base36enc(orphaned_backup->start_time));
749+
750+
orphaned_backup = orphaned_backup->parent_backup_link;
751+
}
752+
753+
base_full_backup = NULL;
754+
break;
755+
}
756+
757+
base_full_backup = base_full_backup->parent_backup_link;
758+
}
759+
760+
return base_full_backup;
761+
}

src/pg_probackup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,8 @@ extern void pgBackupFree(void *backup);
443443
extern int pgBackupCompareId(const void *f1, const void *f2);
444444
extern int pgBackupCompareIdDesc(const void *f1, const void *f2);
445445

446+
extern pgBackup* find_parent_backup(pgBackup *current_backup);
447+
446448
/* in dir.c */
447449
extern void dir_list_file(parray *files, const char *root, bool exclude,
448450
bool omit_symlink, bool add_root);

src/restore.c

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -202,41 +202,40 @@ do_restore_or_validate(time_t target_backup_id,
202202
dest_backup_index = i;
203203
}
204204

205-
/* If we already found dest_backup, look for full backup. */
206-
/* TODO Now, as we have all backups linked, we can probably get rid of that?"*/
207-
if (dest_backup)
205+
}
206+
207+
/* If we already found dest_backup, look for full backup. */
208+
if (dest_backup)
209+
{
210+
base_full_backup = current_backup;
211+
212+
if (current_backup->backup_mode != BACKUP_MODE_FULL)
213+
{
214+
base_full_backup = find_parent_backup(current_backup);
215+
216+
if (base_full_backup == NULL)
217+
elog(ERROR, "Valid full backup for backup %s is not found.",
218+
base36enc(current_backup->start_time));
219+
}
220+
221+
/*
222+
* We have found full backup by link,
223+
* now we need to walk the list to find its index.
224+
*
225+
* TODO I think we should rewrite it someday to use double linked list
226+
* and avoid relying on sort order anymore.
227+
*/
228+
for (i = dest_backup_index; i < parray_num(backups); i++)
208229
{
209-
if (current_backup->backup_mode == BACKUP_MODE_FULL)
230+
pgBackup * temp_backup = (pgBackup *) parray_get(backups, i);
231+
if (temp_backup->start_time == base_full_backup->start_time)
210232
{
211-
if (current_backup->status != BACKUP_STATUS_OK)
212-
{
213-
/* Full backup revalidation can be done only for DONE and CORRUPT */
214-
if (current_backup->status == BACKUP_STATUS_DONE ||
215-
current_backup->status == BACKUP_STATUS_CORRUPT)
216-
elog(WARNING, "base backup %s for given backup %s is in %s status, trying to revalidate",
217-
base36enc_dup(current_backup->start_time),
218-
base36enc_dup(dest_backup->start_time),
219-
status2str(current_backup->status));
220-
else
221-
elog(ERROR, "base backup %s for given backup %s is in %s status",
222-
base36enc_dup(current_backup->start_time),
223-
base36enc_dup(dest_backup->start_time),
224-
status2str(current_backup->status));
225-
}
226-
/* We found both dest and base backups. */
227-
base_full_backup = current_backup;
228233
base_full_backup_index = i;
229234
break;
230235
}
231-
else
232-
/* It`s ok to skip incremental backup */
233-
continue;
234236
}
235237
}
236238

237-
if (base_full_backup == NULL)
238-
elog(ERROR, "Full backup satisfying target options is not found.");
239-
240239
/*
241240
* Ensure that directories provided in tablespace mapping are valid
242241
* i.e. empty or not exist.

src/validate.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -282,44 +282,33 @@ do_validate_instance(void)
282282
if (backups == NULL)
283283
elog(ERROR, "Failed to get backup list.");
284284

285-
/* Valiate each backup along with its xlog files. */
286-
/* TODO Maybe use parent_backup_link instead of looking for backups in the list */
285+
/* Examine backups one by one and validate them */
287286
for (i = 0; i < parray_num(backups); i++)
288287
{
289-
pgBackup *base_full_backup = NULL;
290-
291288
current_backup = (pgBackup *) parray_get(backups, i);
292289

293-
if (current_backup->backup_mode != BACKUP_MODE_FULL)
290+
/* Valiate each backup along with its xlog files. */
291+
pgBackupValidate(current_backup);
292+
293+
/* Ensure that the backup has valid list of parent backups */
294+
if (current_backup->status == BACKUP_STATUS_OK)
294295
{
295-
int j;
296+
pgBackup *base_full_backup = current_backup;
296297

297-
for (j = i + 1; j < parray_num(backups); j++)
298+
if (current_backup->backup_mode != BACKUP_MODE_FULL)
298299
{
299-
pgBackup *backup = (pgBackup *) parray_get(backups, j);
300+
base_full_backup = find_parent_backup(current_backup);
300301

301-
if (backup->backup_mode == BACKUP_MODE_FULL)
302-
{
303-
base_full_backup = backup;
304-
break;
305-
}
302+
if (base_full_backup == NULL)
303+
elog(ERROR, "Valid full backup for backup %s is not found.",
304+
base36enc(current_backup->start_time));
306305
}
307-
}
308-
else
309-
base_full_backup = current_backup;
310-
311-
pgBackupValidate(current_backup);
312306

313-
/* There is no point in wal validation for corrupted backup */
314-
if (current_backup->status == BACKUP_STATUS_OK)
315-
{
316-
if (base_full_backup == NULL)
317-
elog(ERROR, "Valid full backup for backup %s is not found.",
318-
base36enc(current_backup->start_time));
319307
/* Validate corresponding WAL files */
320308
validate_wal(current_backup, arclog_path, 0,
321-
0, base_full_backup->tli);
309+
0, base_full_backup->tli);
322310
}
311+
323312
/* Mark every incremental backup between corrupted backup and nearest FULL backup as orphans */
324313
if (current_backup->status == BACKUP_STATUS_CORRUPT)
325314
{

0 commit comments

Comments
 (0)