diff --git a/src/backup.c b/src/backup.c index f4e93042..fff06049 100644 --- a/src/backup.c +++ b/src/backup.c @@ -931,7 +931,7 @@ do_backup_instance(void) * Entry point of pg_probackup BACKUP subcommand. */ int -do_backup(time_t start_time) +do_backup(time_t start_time, bool no_validate) { /* PGDATA and BACKUP_MODE are always required */ if (instance_config.pgdata == NULL) @@ -1069,7 +1069,8 @@ do_backup(time_t start_time) //elog(LOG, "Backup completed. Total bytes : " INT64_FORMAT "", // current.data_bytes); - pgBackupValidate(¤t); + if (!no_validate) + pgBackupValidate(¤t); elog(INFO, "Backup %s completed", base36enc(current.start_time)); diff --git a/src/catalog.c b/src/catalog.c index b0e6a5e7..766afb95 100644 --- a/src/catalog.c +++ b/src/catalog.c @@ -453,7 +453,8 @@ catalog_get_last_data_backup(parray *backup_list, TimeLineID tli) { backup = (pgBackup *) parray_get(backup_list, (size_t) i); - if (backup->status == BACKUP_STATUS_OK && backup->tli == tli) + if ((backup->status == BACKUP_STATUS_OK || + backup->status == BACKUP_STATUS_DONE) && backup->tli == tli) return backup; } diff --git a/src/delete.c b/src/delete.c index 63c7aac3..a516150b 100644 --- a/src/delete.c +++ b/src/delete.c @@ -94,7 +94,7 @@ do_delete(time_t backup_id) { pgBackup *backup = (pgBackup *) parray_get(backup_list, (size_t) i); - if (backup->status == BACKUP_STATUS_OK) + if (backup->status == BACKUP_STATUS_OK || backup->status == BACKUP_STATUS_DONE) { oldest_lsn = backup->start_lsn; oldest_tli = backup->tli; diff --git a/src/help.c b/src/help.c index 214a15ed..32a9a3ba 100644 --- a/src/help.c +++ b/src/help.c @@ -118,7 +118,7 @@ help_pg_probackup(void) printf(_(" [--master-db=db_name] [--master-host=host_name]\n")); printf(_(" [--master-port=port] [--master-user=user_name]\n")); printf(_(" [--replica-timeout=timeout]\n")); - printf(_(" [--skip-block-validation]\n")); + printf(_(" [--no-validate] [--skip-block-validation]\n")); printf(_(" [--external-dirs=external-directory-path]\n")); printf(_("\n %s restore -B backup-path --instance=instance_name\n"), PROGRAM_NAME); @@ -212,7 +212,7 @@ help_backup(void) printf(_(" [--master-db=db_name] [--master-host=host_name]\n")); printf(_(" [--master-port=port] [--master-user=user_name]\n")); printf(_(" [--replica-timeout=timeout]\n")); - printf(_(" [--skip-block-validation]\n")); + printf(_(" [--no-validate] [--skip-block-validation]\n")); printf(_(" [-E external-dirs=external-directory-path]\n\n")); printf(_(" -B, --backup-path=backup-path location of the backup storage area\n")); @@ -226,6 +226,7 @@ help_backup(void) printf(_(" -j, --threads=NUM number of parallel threads\n")); printf(_(" --archive-timeout=timeout wait timeout for WAL segment archiving (default: 5min)\n")); printf(_(" --progress show progress\n")); + printf(_(" --no-validate disable validation after backup\n")); printf(_(" --skip-block-validation set to validate only file-level checksum\n")); printf(_(" -E --external-dirs=external-directory-path\n")); printf(_(" backup some directories not from pgdata \n")); diff --git a/src/merge.c b/src/merge.c index 8e91babb..b9d9e8aa 100644 --- a/src/merge.c +++ b/src/merge.c @@ -78,6 +78,7 @@ do_merge(time_t backup_id) { /* sanity */ if (backup->status != BACKUP_STATUS_OK && + backup->status != BACKUP_STATUS_DONE && /* It is possible that previous merging was interrupted */ backup->status != BACKUP_STATUS_MERGING && backup->status != BACKUP_STATUS_DELETING) @@ -107,6 +108,7 @@ do_merge(time_t backup_id) /* sanity */ if (full_backup->status != BACKUP_STATUS_OK && + full_backup->status != BACKUP_STATUS_DONE && /* It is possible that previous merging was interrupted */ full_backup->status != BACKUP_STATUS_MERGING) elog(ERROR, "Backup %s has status: %s", @@ -117,6 +119,7 @@ do_merge(time_t backup_id) { /* sanity */ if (dest_backup->status != BACKUP_STATUS_OK && + dest_backup->status != BACKUP_STATUS_DONE && /* It is possible that previous merging was interrupted */ dest_backup->status != BACKUP_STATUS_MERGING && dest_backup->status != BACKUP_STATUS_DELETING) @@ -191,7 +194,8 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup) * BACKUP_STATUS_MERGING status then it isn't valid backup until merging * finished. */ - if (to_backup->status == BACKUP_STATUS_OK) + if (to_backup->status == BACKUP_STATUS_OK || + to_backup->status == BACKUP_STATUS_DONE) { pgBackupValidate(to_backup); if (to_backup->status == BACKUP_STATUS_CORRUPT) @@ -203,6 +207,7 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup) * BACKUP_STATUS_MERGING status. */ Assert(from_backup->status == BACKUP_STATUS_OK || + from_backup->status == BACKUP_STATUS_DONE || from_backup->status == BACKUP_STATUS_MERGING || from_backup->status == BACKUP_STATUS_DELETING); pgBackupValidate(from_backup); diff --git a/src/pg_probackup.c b/src/pg_probackup.c index 24ba2759..0f4931f8 100644 --- a/src/pg_probackup.c +++ b/src/pg_probackup.c @@ -85,7 +85,7 @@ static char *target_action = NULL; static pgRecoveryTarget *recovery_target_options = NULL; bool restore_as_replica = false; -bool restore_no_validate = false; +bool no_validate = false; bool skip_block_validation = false; bool skip_external_dirs = false; @@ -158,7 +158,7 @@ static ConfigOption cmd_options[] = { 's', 141, "recovery-target-name", &target_name, SOURCE_CMD_STRICT }, { 's', 142, "recovery-target-action", &target_action, SOURCE_CMD_STRICT }, { 'b', 'R', "restore-as-replica", &restore_as_replica, SOURCE_CMD_STRICT }, - { 'b', 143, "no-validate", &restore_no_validate, SOURCE_CMD_STRICT }, + { 'b', 143, "no-validate", &no_validate, SOURCE_CMD_STRICT }, { 's', 144, "lsn", &target_lsn, SOURCE_CMD_STRICT }, { 'b', 154, "skip-block-validation", &skip_block_validation, SOURCE_CMD_STRICT }, { 'b', 156, "skip-external-dirs", &skip_external_dirs, SOURCE_CMD_STRICT }, @@ -474,7 +474,7 @@ main(int argc, char *argv[]) /* parse all recovery target options into recovery_target_options structure */ recovery_target_options = parseRecoveryTargetOptions(target_time, target_xid, target_inclusive, target_tli, target_lsn, target_immediate, - target_name, target_action, restore_no_validate); + target_name, target_action, no_validate); } if (num_threads < 1) @@ -508,7 +508,7 @@ main(int argc, char *argv[]) PROGRAM_VERSION, base36enc(start_time), backup_mode, instance_name, stream_wal ? "true" : "false", is_remote_backup ? "true" : "false"); - return do_backup(start_time); + return do_backup(start_time, no_validate); } case RESTORE_CMD: return do_restore_or_validate(current.backup_id, diff --git a/src/pg_probackup.h b/src/pg_probackup.h index ff4ae866..1f66194d 100644 --- a/src/pg_probackup.h +++ b/src/pg_probackup.h @@ -291,7 +291,7 @@ typedef struct pgRecoveryTarget bool recovery_target_immediate; const char *recovery_target_name; const char *recovery_target_action; - bool restore_no_validate; + bool no_validate; } pgRecoveryTarget; typedef struct @@ -406,7 +406,7 @@ extern pgBackup current; extern const char *pgdata_exclude_dir[]; /* in backup.c */ -extern int do_backup(time_t start_time); +extern int do_backup(time_t start_time, bool no_validate); extern BackupMode parse_backup_mode(const char *value); extern const char *deparse_backup_mode(BackupMode mode); extern void process_block_change(ForkNumber forknum, RelFileNode rnode, @@ -427,7 +427,7 @@ extern pgRecoveryTarget *parseRecoveryTargetOptions( const char *target_time, const char *target_xid, const char *target_inclusive, TimeLineID target_tli, const char* target_lsn, bool target_immediate, const char *target_name, - const char *target_action, bool restore_no_validate); + const char *target_action, bool no_validate); /* in merge.c */ extern void do_merge(time_t backup_id); diff --git a/src/restore.c b/src/restore.c index bd8f5b72..04dff24c 100644 --- a/src/restore.c +++ b/src/restore.c @@ -94,7 +94,8 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, if (is_restore && target_backup_id == INVALID_BACKUP_ID && - current_backup->status != BACKUP_STATUS_OK) + (current_backup->status != BACKUP_STATUS_OK && + current_backup->status != BACKUP_STATUS_DONE)) { elog(WARNING, "Skipping backup %s, because it has non-valid status: %s", base36enc(current_backup->start_time), status2str(current_backup->status)); @@ -110,7 +111,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, { /* backup is not ok, - * but in case of CORRUPT, ORPHAN or DONE revalidation is possible + * but in case of CORRUPT or ORPHAN revalidation is possible * unless --no-validate is used, * in other cases throw an error. */ @@ -119,13 +120,13 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, // 3. restore -i INVALID_ID <- allowed revalidate and restore // 4. restore <- impossible // 5. restore --no-validate <- forbidden - if (current_backup->status != BACKUP_STATUS_OK) + if (current_backup->status != BACKUP_STATUS_OK && + current_backup->status != BACKUP_STATUS_DONE) { - if ((current_backup->status == BACKUP_STATUS_DONE || - current_backup->status == BACKUP_STATUS_ORPHAN || + if ((current_backup->status == BACKUP_STATUS_ORPHAN || current_backup->status == BACKUP_STATUS_CORRUPT || current_backup->status == BACKUP_STATUS_RUNNING) - && !rt->restore_no_validate) + && !rt->no_validate) elog(WARNING, "Backup %s has status: %s", base36enc(current_backup->start_time), status2str(current_backup->status)); else @@ -205,7 +206,8 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, */ if (is_parent(missing_backup_start_time, backup, false)) { - if (backup->status == BACKUP_STATUS_OK) + if (backup->status == BACKUP_STATUS_OK || + backup->status == BACKUP_STATUS_DONE) { write_backup_status(backup, BACKUP_STATUS_ORPHAN); @@ -238,7 +240,8 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, if (is_parent(tmp_backup->start_time, backup, false)) { - if (backup->status == BACKUP_STATUS_OK) + if (backup->status == BACKUP_STATUS_OK || + backup->status == BACKUP_STATUS_DONE) { write_backup_status(backup, BACKUP_STATUS_ORPHAN); @@ -308,7 +311,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, parray_append(parent_chain, base_full_backup); /* for validation or restore with enabled validation */ - if (!is_restore || !rt->restore_no_validate) + if (!is_restore || !rt->no_validate) { if (dest_backup->backup_mode != BACKUP_MODE_FULL) elog(INFO, "Validating parents for backup %s", base36enc(dest_backup->start_time)); @@ -374,7 +377,8 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, if (is_parent(corrupted_backup->start_time, backup, false)) { - if (backup->status == BACKUP_STATUS_OK) + if (backup->status == BACKUP_STATUS_OK || + backup->status == BACKUP_STATUS_DONE) { write_backup_status(backup, BACKUP_STATUS_ORPHAN); @@ -393,9 +397,10 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, * If dest backup is corrupted or was orphaned in previous check * produce corresponding error message */ - if (dest_backup->status == BACKUP_STATUS_OK) + if (dest_backup->status == BACKUP_STATUS_OK || + dest_backup->status == BACKUP_STATUS_DONE) { - if (rt->restore_no_validate) + if (rt->no_validate) elog(INFO, "Backup %s is used without validation.", base36enc(dest_backup->start_time)); else elog(INFO, "Backup %s is valid.", base36enc(dest_backup->start_time)); @@ -425,7 +430,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, * Backup was locked during validation if no-validate wasn't * specified. */ - if (rt->restore_no_validate && !lock_backup(backup)) + if (rt->no_validate && !lock_backup(backup)) elog(ERROR, "Cannot lock backup directory"); restore_backup(backup, dest_backup->external_dir_str); @@ -473,7 +478,8 @@ restore_backup(pgBackup *backup, const char *external_dir_str) bool restore_isok = true; - if (backup->status != BACKUP_STATUS_OK) + if (backup->status != BACKUP_STATUS_OK && + backup->status != BACKUP_STATUS_DONE) elog(ERROR, "Backup %s cannot be restored because it is not valid", base36enc(backup->start_time)); @@ -993,7 +999,7 @@ parseRecoveryTargetOptions(const char *target_time, bool target_immediate, const char *target_name, const char *target_action, - bool restore_no_validate) + bool no_validate) { time_t dummy_time; TransactionId dummy_xid; @@ -1022,7 +1028,7 @@ parseRecoveryTargetOptions(const char *target_time, rt->recovery_target_immediate = false; rt->recovery_target_name = NULL; rt->recovery_target_action = NULL; - rt->restore_no_validate = false; + rt->no_validate = false; /* parse given options */ if (target_time) @@ -1080,9 +1086,9 @@ parseRecoveryTargetOptions(const char *target_time, rt->recovery_target_immediate = target_immediate; } - if (restore_no_validate) + if (no_validate) { - rt->restore_no_validate = restore_no_validate; + rt->no_validate = no_validate; } if (target_name) diff --git a/src/validate.c b/src/validate.c index 472f7246..b7825f4d 100644 --- a/src/validate.c +++ b/src/validate.c @@ -417,7 +417,8 @@ do_validate_instance(void) corrupted_backup_found = true; /* orphanize current_backup */ - if (current_backup->status == BACKUP_STATUS_OK) + if (current_backup->status == BACKUP_STATUS_OK || + current_backup->status == BACKUP_STATUS_DONE) { write_backup_status(current_backup, BACKUP_STATUS_ORPHAN); elog(WARNING, "Backup %s is orphaned because his parent %s is missing", @@ -440,7 +441,8 @@ do_validate_instance(void) { char *backup_id = base36enc_dup(tmp_backup->start_time); /* orphanize current_backup */ - if (current_backup->status == BACKUP_STATUS_OK) + if (current_backup->status == BACKUP_STATUS_OK || + current_backup->status == BACKUP_STATUS_DONE) { write_backup_status(current_backup, BACKUP_STATUS_ORPHAN); elog(WARNING, "Backup %s is orphaned because his parent %s has status: %s", @@ -512,7 +514,8 @@ do_validate_instance(void) if (is_parent(current_backup->start_time, backup, false)) { - if (backup->status == BACKUP_STATUS_OK) + if (backup->status == BACKUP_STATUS_OK || + backup->status == BACKUP_STATUS_DONE) { write_backup_status(backup, BACKUP_STATUS_ORPHAN); diff --git a/tests/expected/option_help.out b/tests/expected/option_help.out index cac631c1..6cb27758 100644 --- a/tests/expected/option_help.out +++ b/tests/expected/option_help.out @@ -50,7 +50,7 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database. [--master-db=db_name] [--master-host=host_name] [--master-port=port] [--master-user=user_name] [--replica-timeout=timeout] - [--skip-block-validation] + [--no-validate] [--skip-block-validation] [--external-dirs=external-directory-path] pg_probackup restore -B backup-path --instance=instance_name