@@ -90,8 +90,10 @@ do_restore_or_validate(time_t target_backup_id,
9090 pgBackup * current_backup = NULL ;
9191 pgBackup * dest_backup = NULL ;
9292 pgBackup * base_full_backup = NULL ;
93+ pgBackup * corrupted_backup = NULL ;
9394 int dest_backup_index = 0 ;
9495 int base_full_backup_index = 0 ;
96+ int corrupted_backup_index = 0 ;
9597 char * action = is_restore ? "Restore" :"Validate" ;
9698
9799 if (is_restore )
@@ -193,8 +195,8 @@ do_restore_or_validate(time_t target_backup_id,
193195 {
194196 if (current_backup -> status != BACKUP_STATUS_OK )
195197 elog (ERROR , "base backup %s for given backup %s is in %s status" ,
196- base36enc (current_backup -> start_time ),
197- base36enc (dest_backup -> start_time ),
198+ base36enc_dup (current_backup -> start_time ),
199+ base36enc_dup (dest_backup -> start_time ),
198200 status2str (current_backup -> status ));
199201 else
200202 {
@@ -205,7 +207,7 @@ do_restore_or_validate(time_t target_backup_id,
205207 }
206208 }
207209 else
208- /* Skip differential backups are ok */
210+ /* It`s ok to skip incremental backup */
209211 continue ;
210212 }
211213 }
@@ -220,36 +222,87 @@ do_restore_or_validate(time_t target_backup_id,
220222 if (is_restore )
221223 check_tablespace_mapping (dest_backup );
222224
225+ if (dest_backup -> backup_mode != BACKUP_MODE_FULL )
226+ elog (INFO , "Validating parents for backup %s" , base36enc (dest_backup -> start_time ));
227+
223228 /*
224229 * Validate backups from base_full_backup to dest_backup.
225230 */
226231 for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
227232 {
228233 pgBackup * backup = (pgBackup * ) parray_get (backups , i );
229234 pgBackupValidate (backup );
235+ if (backup -> status == BACKUP_STATUS_CORRUPT )
236+ {
237+ corrupted_backup = backup ;
238+ corrupted_backup_index = i ;
239+ break ;
240+ }
241+ }
242+ /* There is no point in wal validation
243+ * if there is corrupted backup between base_backup and dest_backup
244+ */
245+ if (!corrupted_backup )
246+ /*
247+ * Validate corresponding WAL files.
248+ * We pass base_full_backup timeline as last argument to this function,
249+ * because it's needed to form the name of xlog file.
250+ */
251+ validate_wal (dest_backup , arclog_path , rt -> recovery_target_time ,
252+ rt -> recovery_target_xid , base_full_backup -> tli );
253+
254+ /* Set every incremental backup between corrupted backup and nearest FULL backup as orphans */
255+ if (corrupted_backup )
256+ {
257+ for (i = corrupted_backup_index - 1 ; i >= 0 ; i -- )
258+ {
259+ pgBackup * backup = (pgBackup * ) parray_get (backups , i );
260+ /* Mark incremental OK backup as orphan */
261+ if (backup -> backup_mode == BACKUP_MODE_FULL )
262+ break ;
263+ if (backup -> status != BACKUP_STATUS_OK )
264+ continue ;
265+ else
266+ {
267+ char * backup_id ,
268+ * corrupted_backup_id ;
269+
270+ backup -> status = BACKUP_STATUS_ORPHAN ;
271+ pgBackupWriteBackupControlFile (backup );
272+
273+ backup_id = base36enc_dup (backup -> start_time );
274+ corrupted_backup_id = base36enc_dup (corrupted_backup -> start_time );
275+
276+ elog (WARNING , "Backup %s is orphaned because his parent %s is corrupted" ,
277+ backup_id , corrupted_backup_id );
278+
279+ free (backup_id );
280+ free (corrupted_backup_id );
281+ }
282+ }
230283 }
231284
232285 /*
233- * Validate corresponding WAL files.
234- * We pass base_full_backup timeline as last argument to this function,
235- * because it's needed to form the name of xlog file.
286+ * If dest backup is corrupted or was orphaned in previous check
287+ * produce corresponding error message
236288 */
237- validate_wal (dest_backup , arclog_path , rt -> recovery_target_time ,
238- rt -> recovery_target_xid , base_full_backup -> tli );
239-
289+ if (dest_backup -> status == BACKUP_STATUS_OK )
290+ elog (INFO , "Backup %s is valid." , base36enc (dest_backup -> start_time ));
291+ else if (dest_backup -> status == BACKUP_STATUS_CORRUPT )
292+ elog (ERROR , "Backup %s is corrupt." , base36enc (dest_backup -> start_time ));
293+ else if (dest_backup -> status == BACKUP_STATUS_ORPHAN )
294+ elog (ERROR , "Backup %s is orphan." , base36enc (dest_backup -> start_time ));
295+ else
296+ elog (ERROR , "Backup %s has status: %s" ,
297+ base36enc (dest_backup -> start_time ), status2str (dest_backup -> status ));
240298
241299 /* We ensured that all backups are valid, now restore if required */
242300 if (is_restore )
243301 {
244- pgBackup * backup ;
245302 for (i = base_full_backup_index ; i >= dest_backup_index ; i -- )
246303 {
247- backup = (pgBackup * ) parray_get (backups , i );
248- if (backup -> status == BACKUP_STATUS_OK )
249- restore_backup (backup );
250- else
251- elog (ERROR , "backup %s is not valid" ,
252- base36enc (backup -> start_time ));
304+ pgBackup * backup = (pgBackup * ) parray_get (backups , i );
305+ restore_backup (backup );
253306 }
254307
255308 /*
@@ -366,13 +419,7 @@ restore_backup(pgBackup *backup)
366419 parray_free (files );
367420
368421 if (LOG_LEVEL_CONSOLE <= LOG || LOG_LEVEL_FILE <= LOG )
369- {
370- char * backup_id ;
371-
372- backup_id = base36enc (backup -> start_time );
373- elog (LOG , "restore %s backup completed" , backup_id );
374- free (backup_id );
375- }
422+ elog (LOG , "restore %s backup completed" , base36enc (backup -> start_time ));
376423}
377424
378425/*
@@ -592,13 +639,8 @@ check_tablespace_mapping(pgBackup *backup)
592639 read_tablespace_map (links , this_backup_path );
593640
594641 if (LOG_LEVEL_CONSOLE <= LOG || LOG_LEVEL_FILE <= LOG )
595- {
596- char * backup_id ;
597-
598- backup_id = base36enc (backup -> start_time );
599- elog (LOG , "check tablespace directories of backup %s" , backup_id );
600- pfree (backup_id );
601- }
642+ elog (LOG , "check tablespace directories of backup %s" ,
643+ base36enc (backup -> start_time ));
602644
603645 /* 1 - each OLDDIR must have an entry in tablespace_map file (links) */
604646 for (cell = tablespace_dirs .head ; cell ; cell = cell -> next )
0 commit comments