/* * Validate files in the backup and update its status to OK. * If any of files are corrupted, update its stutus to CORRUPT. */ int do_validate(pgBackupRange *range) { int i; parray *backup_list; int ret; bool another_pg_rman = false; ret = catalog_lock(); if (ret == 1) another_pg_rman = true; /* get backup list matches given range */ backup_list = catalog_get_backup_list(range); if(!backup_list) { elog(ERROR_SYSTEM, _("can't process any more.")); } parray_qsort(backup_list, pgBackupCompareId); for (i = 0; i < parray_num(backup_list); i++) { pgBackup *backup = (pgBackup *)parray_get(backup_list, i); /* clean extra backups (switch STATUS to ERROR) */ if(!another_pg_rman && (backup->status == BACKUP_STATUS_RUNNING || backup->status == BACKUP_STATUS_DELETING)) { backup->status = BACKUP_STATUS_ERROR; pgBackupWriteIni(backup); } /* Validate completed backups only. */ if (backup->status != BACKUP_STATUS_DONE) continue; /* validate with CRC value and update status to OK */ pgBackupValidate(backup, false, false, (HAVE_DATABASE(backup))); } /* cleanup */ parray_walk(backup_list, pgBackupFree); parray_free(backup_list); catalog_unlock(); return 0; }
/* * Delete backup files of the backup and update the status of the backup to * BACKUP_STATUS_DELETED. */ static int pgBackupDeleteFiles(pgBackup *backup) { int i; char path[MAXPGPATH]; char timestamp[20]; parray *files; /* * If the backup was deleted already, there is nothing to do. */ if (backup->status == BACKUP_STATUS_DELETED) return 0; time2iso(timestamp, lengthof(timestamp), backup->start_time); elog(INFO, "delete: %s", timestamp); /* * Update STATUS to BACKUP_STATUS_DELETING in preparation for the case which * the error occurs before deleting all backup files. */ if (!check) { backup->status = BACKUP_STATUS_DELETING; pgBackupWriteIni(backup); } /* list files to be deleted */ files = parray_new(); pgBackupGetPath(backup, path, lengthof(path), DATABASE_DIR); dir_list_file(files, path, NULL, true, true); /* delete leaf node first */ parray_qsort(files, pgFileComparePathDesc); for (i = 0; i < parray_num(files); i++) { pgFile *file = (pgFile *) parray_get(files, i); /* print progress */ elog(LOG, "delete file(%d/%lu) \"%s\"", i + 1, (unsigned long) parray_num(files), file->path); /* skip actual deletion in check mode */ if (!check) { if (remove(file->path)) { elog(WARNING, "can't remove \"%s\": %s", file->path, strerror(errno)); parray_walk(files, pgFileFree); parray_free(files); return 1; } } } /* * After deleting all of the backup files, update STATUS to * BACKUP_STATUS_DELETED. */ if (!check) { backup->status = BACKUP_STATUS_DELETED; pgBackupWriteIni(backup); } parray_walk(files, pgFileFree); parray_free(files); return 0; }
/* * Validate each files in the backup with its size. */ void pgBackupValidate(pgBackup *backup, bool size_only, bool for_get_timeline, bool with_database) { char timestamp[100]; char base_path[MAXPGPATH]; char path[MAXPGPATH]; parray *files; bool corrupted = false; time2iso(timestamp, lengthof(timestamp), backup->start_time); if(!for_get_timeline) { if (with_database) elog(INFO, "validate: %s backup and archive log files by %s", timestamp, (size_only ? "SIZE" : "CRC")); else { if (backup->backup_mode == BACKUP_MODE_ARCHIVE) elog(INFO, "validate: %s archive log files by %s", timestamp, (size_only ? "SIZE" : "CRC")); else if (backup->with_serverlog) elog(INFO, "validate: %s server log files by %s", timestamp, (size_only ? "SIZE" : "CRC")); } } if(!check) { if (HAVE_DATABASE(backup)) { elog(LOG, "database files..."); pgBackupGetPath(backup, base_path, lengthof(base_path), DATABASE_DIR); pgBackupGetPath(backup, path, lengthof(path), DATABASE_FILE_LIST); files = dir_read_file_list(base_path, path); if (!pgBackupValidateFiles(files, base_path, size_only)) corrupted = true; parray_walk(files, pgFileFree); parray_free(files); } if (HAVE_ARCLOG(backup)) { elog(LOG, "archive WAL files..."); pgBackupGetPath(backup, base_path, lengthof(base_path), ARCLOG_DIR); pgBackupGetPath(backup, path, lengthof(path), ARCLOG_FILE_LIST); files = dir_read_file_list(base_path, path); if (!pgBackupValidateFiles(files, base_path, size_only)) corrupted = true; parray_walk(files, pgFileFree); parray_free(files); } if (backup->with_serverlog) { elog(LOG, "server log files..."); pgBackupGetPath(backup, base_path, lengthof(base_path), SRVLOG_DIR); pgBackupGetPath(backup, path, lengthof(path), SRVLOG_FILE_LIST); files = dir_read_file_list(base_path, path); if (!pgBackupValidateFiles(files, base_path, size_only)) corrupted = true; parray_walk(files, pgFileFree); parray_free(files); } /* update status to OK */ if (corrupted) backup->status = BACKUP_STATUS_CORRUPT; else backup->status = BACKUP_STATUS_OK; pgBackupWriteIni(backup); if (corrupted) elog(WARNING, "backup %s is corrupted", timestamp); else elog(LOG, "backup %s is valid", timestamp); } }