@@ -57,6 +57,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
5757 int base_full_backup_index = 0 ;
5858 int corrupted_backup_index = 0 ;
5959 char * action = is_restore ? "Restore" :"Validate" ;
60+ parray * parent_chain = NULL ;
6061
6162 if (is_restore )
6263 {
@@ -283,34 +284,54 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
283284 if (is_restore )
284285 check_tablespace_mapping (dest_backup );
285286
287+ /* At this point we are sure that parent chain is whole
288+ * so we can build separate array, containing all needed backups,
289+ * to simplify validation and restore
290+ */
291+ parent_chain = parray_new ();
292+
293+ /* Take every backup that is a child of base_backup AND parent of dest_backup
294+ * including base_backup and dest_backup
295+ */
296+ for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
297+ {
298+ tmp_backup = (pgBackup * ) parray_get (backups , i );
299+
300+ if (is_parent (base_full_backup -> start_time , tmp_backup , true) &&
301+ is_parent (tmp_backup -> start_time , dest_backup , true))
302+ {
303+ parray_append (parent_chain , tmp_backup );
304+ }
305+ }
306+
307+ /* for validation or restore with enabled validation */
286308 if (!is_restore || !rt -> restore_no_validate )
287309 {
288310 if (dest_backup -> backup_mode != BACKUP_MODE_FULL )
289311 elog (INFO , "Validating parents for backup %s" , base36enc (dest_backup -> start_time ));
290312
291313 /*
292314 * Validate backups from base_full_backup to dest_backup.
293- * At this point we are sure that parent chain is intact.
294315 */
295- for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
316+ for (i = 0 ; i < parray_num ( parent_chain ) ; i ++ )
296317 {
297- tmp_backup = (pgBackup * ) parray_get (backups , i );
318+ tmp_backup = (pgBackup * ) parray_get (parent_chain , i );
298319
299- if (is_parent (base_full_backup -> start_time , tmp_backup , true))
320+ lock_backup (tmp_backup );
321+ pgBackupValidate (tmp_backup );
322+ /* Maybe we should be more paranoid and check for !BACKUP_STATUS_OK? */
323+ if (tmp_backup -> status == BACKUP_STATUS_CORRUPT )
300324 {
301- lock_backup (tmp_backup );
302- pgBackupValidate (tmp_backup );
303- /* Maybe we should be more paranoid and check for !BACKUP_STATUS_OK? */
304- if (tmp_backup -> status == BACKUP_STATUS_CORRUPT )
305- {
306- corrupted_backup = tmp_backup ;
307- corrupted_backup_index = i ;
308- break ;
309- }
310- /* We do not validate WAL files of intermediate backups
311- * It`s done to speed up restore
325+ corrupted_backup = tmp_backup ;
326+ /* we need corrupted backup index from 'backups' not parent_chain
327+ * so we can properly orphanize all its descendants
312328 */
329+ corrupted_backup_index = get_backup_index_number (backups , corrupted_backup );
330+ break ;
313331 }
332+ /* We do not validate WAL files of intermediate backups
333+ * It`s done to speed up restore
334+ */
314335 }
315336
316337 /* There is no point in wal validation of corrupted backups */
@@ -353,7 +374,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
353374 }
354375 }
355376
356- // TODO: rewrite restore to use parent_chain
357377 /*
358378 * If dest backup is corrupted or was orphaned in previous check
359379 * produce corresponding error message
@@ -374,13 +394,12 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
374394 base36enc (dest_backup -> start_time ), status2str (dest_backup -> status ));
375395
376396 /* We ensured that all backups are valid, now restore if required
377- * TODO: use parent_link
378397 */
379398 if (is_restore )
380399 {
381- for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
400+ for (i = 0 ; i < parray_num ( parent_chain ) ; i ++ )
382401 {
383- pgBackup * backup = (pgBackup * ) parray_get (backups , i );
402+ pgBackup * backup = (pgBackup * ) parray_get (parent_chain , i );
384403
385404 if (rt -> lsn_specified && parse_server_version (backup -> server_version ) < 100000 )
386405 elog (ERROR , "Backup %s was created for version %s which doesn't support recovery_target_lsn" ,
@@ -410,6 +429,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
410429 /* cleanup */
411430 parray_walk (backups , pgBackupFree );
412431 parray_free (backups );
432+ parray_free (parent_chain );
413433
414434 elog (INFO , "%s of backup %s completed." ,
415435 action , base36enc (dest_backup -> start_time ));
@@ -485,6 +505,7 @@ restore_backup(pgBackup *backup)
485505 /* By default there are some error */
486506 threads_args [i ].ret = 1 ;
487507
508+ /* Useless message TODO: rewrite */
488509 elog (LOG , "Start thread for num:%zu" , parray_num (files ));
489510
490511 pthread_create (& threads [i ], NULL , restore_files , arg );
0 commit comments