/* * 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; }
int do_delete(pgBackupRange *range) { int i; int ret; parray *backup_list; bool do_delete = false; XLogRecPtr oldest_lsn = InvalidXLogRecPtr; TimeLineID oldest_tli; /* DATE are always required */ if (!pgBackupRangeIsValid(range)) elog(ERROR, "required delete range option not specified: delete DATE"); /* Lock backup catalog */ ret = catalog_lock(); if (ret == -1) elog(ERROR, "can't lock backup catalog."); else if (ret == 1) elog(ERROR, "another pg_arman is running, stop delete."); /* Get complete list of backups */ backup_list = catalog_get_backup_list(NULL); if (!backup_list) elog(ERROR, "No backup list found, can't process any more."); /* Find backups to be deleted */ for (i = 0; i < parray_num(backup_list); i++) { pgBackup *backup = (pgBackup *) parray_get(backup_list, i); /* delete backup and update status to DELETED */ if (do_delete) { /* check for interrupt */ if (interrupted) elog(ERROR, "interrupted during delete backup"); pgBackupDeleteFiles(backup); continue; } /* Found the latest full backup */ if (backup->backup_mode >= BACKUP_MODE_FULL && backup->status == BACKUP_STATUS_OK && backup->start_time <= range->begin) { do_delete = true; oldest_lsn = backup->start_lsn; oldest_tli = backup->tli; } } /* release catalog lock */ catalog_unlock(); /* cleanup */ parray_walk(backup_list, pgBackupFree); parray_free(backup_list); /* * Delete in archive WAL segments that are not needed anymore. The oldest * segment to be kept is the first segment that the oldest full backup * found around needs to keep. */ if (!XLogRecPtrIsInvalid(oldest_lsn)) { XLogSegNo targetSegNo; char oldestSegmentNeeded[MAXFNAMELEN]; DIR *arcdir; struct dirent *arcde; char wal_file[MAXPGPATH]; int rc; XLByteToSeg(oldest_lsn, targetSegNo); XLogFileName(oldestSegmentNeeded, oldest_tli, targetSegNo); elog(LOG, "Removing segments older than %s", oldestSegmentNeeded); /* * Now is time to do the actual work and to remove all the segments * not needed anymore. */ if ((arcdir = opendir(arclog_path)) != NULL) { while (errno = 0, (arcde = readdir(arcdir)) != NULL) { /* * We ignore the timeline part of the XLOG segment identifiers in * deciding whether a segment is still needed. This ensures that * we won't prematurely remove a segment from a parent timeline. * We could probably be a little more proactive about removing * segments of non-parent timelines, but that would be a whole lot * more complicated. * * We use the alphanumeric sorting property of the filenames to * decide which ones are earlier than the exclusiveCleanupFileName * file. Note that this means files are not removed in the order * they were originally written, in case this worries you. */ if ((IsXLogFileName(arcde->d_name) || IsPartialXLogFileName(arcde->d_name)) && strcmp(arcde->d_name + 8, oldestSegmentNeeded + 8) < 0) { /* * Use the original file name again now, including any * extension that might have been chopped off before testing * the sequence. */ snprintf(wal_file, MAXPGPATH, "%s/%s", arclog_path, arcde->d_name); rc = unlink(wal_file); if (rc != 0) { elog(WARNING, "could not remove file \"%s\": %s", wal_file, strerror(errno)); break; } elog(LOG, "removed WAL segment \"%s\"", wal_file); } } if (errno) elog(WARNING, "could not read archive location \"%s\": %s", arclog_path, strerror(errno)); if (closedir(arcdir)) elog(WARNING, "could not close archive location \"%s\": %s", arclog_path, strerror(errno)); } else elog(WARNING, "could not open archive location \"%s\": %s", arclog_path, strerror(errno)); } return 0; }