@@ -57,6 +57,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
57
57
int base_full_backup_index = 0 ;
58
58
int corrupted_backup_index = 0 ;
59
59
char * action = is_restore ? "Restore" :"Validate" ;
60
+ parray * parent_chain = NULL ;
60
61
61
62
if (is_restore )
62
63
{
@@ -285,34 +286,53 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
285
286
if (is_restore )
286
287
check_tablespace_mapping (dest_backup );
287
288
289
+ /* At this point we are sure that parent chain is whole
290
+ * so we can build separate array, containing all needed backups,
291
+ * to simplify validation and restore
292
+ */
293
+ parent_chain = parray_new ();
294
+
295
+ /* Take every backup that is a child of base_backup AND parent of dest_backup
296
+ * including base_backup and dest_backup
297
+ */
298
+ for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
299
+ {
300
+ tmp_backup = (pgBackup * ) parray_get (backups , i );
301
+
302
+ if (is_parent (base_full_backup -> start_time , tmp_backup , true) &&
303
+ is_parent (tmp_backup -> start_time , dest_backup , true))
304
+ {
305
+ parray_append (parent_chain , tmp_backup );
306
+ }
307
+ }
308
+
309
+ /* for validation or restore with enabled validation */
288
310
if (!is_restore || !rt -> restore_no_validate )
289
311
{
290
312
if (dest_backup -> backup_mode != BACKUP_MODE_FULL )
291
313
elog (INFO , "Validating parents for backup %s" , base36enc (dest_backup -> start_time ));
292
314
293
315
/*
294
316
* Validate backups from base_full_backup to dest_backup.
295
- * At this point we are sure that parent chain is intact.
296
317
*/
297
- for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
318
+ for (i = 0 ; i < parray_num ( parent_chain ) ; i ++ )
298
319
{
299
- tmp_backup = (pgBackup * ) parray_get (backups , i );
320
+ tmp_backup = (pgBackup * ) parray_get (parent_chain , i );
300
321
301
- if (is_parent (base_full_backup -> start_time , tmp_backup , true))
322
+ pgBackupValidate (tmp_backup );
323
+ /* Maybe we should be more paranoid and check for !BACKUP_STATUS_OK? */
324
+ if (tmp_backup -> status == BACKUP_STATUS_CORRUPT )
302
325
{
303
-
304
- pgBackupValidate (tmp_backup );
305
- /* Maybe we should be more paranoid and check for !BACKUP_STATUS_OK? */
306
- if (tmp_backup -> status == BACKUP_STATUS_CORRUPT )
307
- {
308
- corrupted_backup = tmp_backup ;
309
- corrupted_backup_index = i ;
310
- break ;
311
- }
312
- /* We do not validate WAL files of intermediate backups
313
- * It`s done to speed up restore
326
+ corrupted_backup = tmp_backup ;
327
+ /* we need corrupted backup index from 'backups' not parent_chain
328
+ * so we can properly orphanize all its descendants
314
329
*/
330
+ corrupted_backup_index = get_backup_index_number (backups , corrupted_backup );
331
+ break ;
315
332
}
333
+ /* We do not validate WAL files of intermediate backups
334
+ * It`s done to speed up restore
335
+ */
316
336
}
317
337
318
338
/* There is no point in wal validation of corrupted backups */
@@ -355,7 +375,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
355
375
}
356
376
}
357
377
358
- // TODO: rewrite restore to use parent_chain
359
378
/*
360
379
* If dest backup is corrupted or was orphaned in previous check
361
380
* produce corresponding error message
@@ -376,13 +395,12 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
376
395
base36enc (dest_backup -> start_time ), status2str (dest_backup -> status ));
377
396
378
397
/* We ensured that all backups are valid, now restore if required
379
- * TODO: use parent_link
380
398
*/
381
399
if (is_restore )
382
400
{
383
- for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
401
+ for (i = 0 ; i < parray_num ( parent_chain ) ; i ++ )
384
402
{
385
- pgBackup * backup = (pgBackup * ) parray_get (backups , i );
403
+ pgBackup * backup = (pgBackup * ) parray_get (parent_chain , i );
386
404
387
405
if (rt -> lsn_specified && parse_server_version (backup -> server_version ) < 100000 )
388
406
elog (ERROR , "Backup %s was created for version %s which doesn't support recovery_target_lsn" ,
@@ -405,6 +423,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
405
423
/* cleanup */
406
424
parray_walk (backups , pgBackupFree );
407
425
parray_free (backups );
426
+ parray_free (parent_chain );
408
427
409
428
elog (INFO , "%s of backup %s completed." ,
410
429
action , base36enc (dest_backup -> start_time ));
@@ -480,6 +499,7 @@ restore_backup(pgBackup *backup)
480
499
/* By default there are some error */
481
500
threads_args [i ].ret = 1 ;
482
501
502
+ /* Useless message TODO: rewrite */
483
503
elog (LOG , "Start thread for num:%zu" , parray_num (files ));
484
504
485
505
pthread_create (& threads [i ], NULL , restore_files , arg );
0 commit comments