Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
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;
}