mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-01-06 13:26:28 +02:00
[Issue #120] Review
This commit is contained in:
parent
d5d58f54a9
commit
9864f5816e
@ -3239,7 +3239,7 @@ pg_probackup delete -B <replaceable>backup_dir</replaceable> --instance <replace
|
|||||||
policy, without performing any irreversible actions.
|
policy, without performing any irreversible actions.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To delete all backups with some status, use the <option>--status</option>:
|
To delete all backups with specific status, use the <option>--status</option>:
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
pg_probackup delete -B <replaceable>backup_dir</replaceable> --instance <replaceable>instance_name</replaceable> --status=ERROR
|
pg_probackup delete -B <replaceable>backup_dir</replaceable> --instance <replaceable>instance_name</replaceable> --status=ERROR
|
||||||
|
61
src/delete.c
61
src/delete.c
@ -123,7 +123,7 @@ do_delete(time_t backup_id)
|
|||||||
* which FULL backup should be keeped for redundancy obligation(only valid do),
|
* which FULL backup should be keeped for redundancy obligation(only valid do),
|
||||||
* but if invalid backup is not guarded by retention - it is removed
|
* but if invalid backup is not guarded by retention - it is removed
|
||||||
*/
|
*/
|
||||||
int do_retention(void)
|
void do_retention(void)
|
||||||
{
|
{
|
||||||
parray *backup_list = NULL;
|
parray *backup_list = NULL;
|
||||||
parray *to_keep_list = parray_new();
|
parray *to_keep_list = parray_new();
|
||||||
@ -154,7 +154,7 @@ int do_retention(void)
|
|||||||
/* Retention is disabled but we still can cleanup wal */
|
/* Retention is disabled but we still can cleanup wal */
|
||||||
elog(WARNING, "Retention policy is not set");
|
elog(WARNING, "Retention policy is not set");
|
||||||
if (!delete_wal)
|
if (!delete_wal)
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* At least one retention policy is active */
|
/* At least one retention policy is active */
|
||||||
@ -196,9 +196,6 @@ int do_retention(void)
|
|||||||
parray_free(backup_list);
|
parray_free(backup_list);
|
||||||
parray_free(to_keep_list);
|
parray_free(to_keep_list);
|
||||||
parray_free(to_purge_list);
|
parray_free(to_purge_list);
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate every backup by retention policies and populate purge and keep lists.
|
/* Evaluate every backup by retention policies and populate purge and keep lists.
|
||||||
@ -1024,42 +1021,58 @@ do_delete_instance(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete all error backup files of given instance. */
|
/* Delete all backups of given status in instance */
|
||||||
int
|
void
|
||||||
do_delete_status(char* status)
|
do_delete_status(InstanceConfig *instance_config, const char *status)
|
||||||
{
|
{
|
||||||
parray *backup_list;
|
parray *backup_list;
|
||||||
parray *xlog_files_list;
|
|
||||||
int i;
|
int i;
|
||||||
int rc;
|
const char *pretty_status;
|
||||||
char instance_config_path[MAXPGPATH];
|
int n_deleted = 0;
|
||||||
|
|
||||||
BackupStatus status_for_delete;
|
|
||||||
|
|
||||||
status_for_delete = str2status(status);
|
BackupStatus status_for_delete = str2status(status);
|
||||||
|
|
||||||
if (status_for_delete == BACKUP_STATUS_INVALID)
|
if (status_for_delete == BACKUP_STATUS_INVALID)
|
||||||
elog(ERROR, "Unknown '%s' value for --status option", status);
|
elog(ERROR, "Unknown value for '--status' option: '%s'", status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User may have provided status string in lower case, but
|
||||||
|
* we should print backup statuses consistently with show command,
|
||||||
|
* so convert it.
|
||||||
|
*/
|
||||||
|
pretty_status = status2str(status_for_delete);
|
||||||
|
|
||||||
/* Delete all error backups. */
|
backup_list = catalog_get_backup_list(instance_config->name, INVALID_BACKUP_ID);
|
||||||
backup_list = catalog_get_backup_list(instance_name, INVALID_BACKUP_ID);
|
|
||||||
|
|
||||||
|
if (parray_num(backup_list) == 0)
|
||||||
|
{
|
||||||
|
elog(WARNING, "Instance '%s' has no backups", instance_config->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
elog(INFO, "Deleting all backups with status '%s'", pretty_status);
|
||||||
|
|
||||||
|
/* Delete all backups with specified status */
|
||||||
for (i = 0; i < parray_num(backup_list); i++)
|
for (i = 0; i < parray_num(backup_list); i++)
|
||||||
{
|
{
|
||||||
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
|
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
|
||||||
if (backup->status == status_for_delete){
|
|
||||||
/* elog(INFO, "Delete error backup '%s' ", base36enc(backup->backup_id)); */
|
if (backup->status == status_for_delete)
|
||||||
catalog_lock_backup_list(backup_list, i, i);
|
{
|
||||||
|
lock_backup(backup);
|
||||||
delete_backup_files(backup);
|
delete_backup_files(backup);
|
||||||
|
n_deleted++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n_deleted > 0)
|
||||||
|
elog(INFO, "Successfully deleted all backups with status '%s' from instance '%s'",
|
||||||
|
pretty_status, instance_config->name);
|
||||||
|
else
|
||||||
|
elog(WARNING, "Instance '%s' has no backups with status '%s'",
|
||||||
|
instance_config->name, pretty_status);
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
parray_walk(backup_list, pgBackupFree);
|
parray_walk(backup_list, pgBackupFree);
|
||||||
parray_free(backup_list);
|
parray_free(backup_list);
|
||||||
|
|
||||||
|
|
||||||
elog(INFO, "Backups with status '%s' from instance '%s' successfully deleted", status, instance_name);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -806,14 +806,16 @@ main(int argc, char *argv[])
|
|||||||
elog(ERROR, "You cannot specify --merge-expired and (-i, --backup-id) options together");
|
elog(ERROR, "You cannot specify --merge-expired and (-i, --backup-id) options together");
|
||||||
if (delete_status && backup_id_string)
|
if (delete_status && backup_id_string)
|
||||||
elog(ERROR, "You cannot specify --status and (-i, --backup-id) options together");
|
elog(ERROR, "You cannot specify --status and (-i, --backup-id) options together");
|
||||||
if (!delete_expired && !merge_expired && !delete_wal && delete_status==NULL && !backup_id_string)
|
if (!delete_expired && !merge_expired && !delete_wal && delete_status == NULL && !backup_id_string)
|
||||||
elog(ERROR, "You must specify at least one of the delete options: "
|
elog(ERROR, "You must specify at least one of the delete options: "
|
||||||
"--delete-expired |--delete-wal |--merge-expired |--status |(-i, --backup-id)");
|
"--delete-expired |--delete-wal |--merge-expired |--status |(-i, --backup-id)");
|
||||||
if (!backup_id_string)
|
if (!backup_id_string)
|
||||||
if (delete_status)
|
{
|
||||||
do_delete_status(delete_status);
|
if (delete_status)
|
||||||
|
do_delete_status(&instance_config, delete_status);
|
||||||
else
|
else
|
||||||
return do_retention();
|
do_retention();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
do_delete(current.backup_id);
|
do_delete(current.backup_id);
|
||||||
break;
|
break;
|
||||||
|
@ -709,9 +709,9 @@ extern int do_show(const char *instance_name, time_t requested_backup_id, bool s
|
|||||||
/* in delete.c */
|
/* in delete.c */
|
||||||
extern void do_delete(time_t backup_id);
|
extern void do_delete(time_t backup_id);
|
||||||
extern void delete_backup_files(pgBackup *backup);
|
extern void delete_backup_files(pgBackup *backup);
|
||||||
extern int do_retention(void);
|
extern void do_retention(void);
|
||||||
extern int do_delete_instance(void);
|
extern int do_delete_instance(void);
|
||||||
extern int do_delete_status(char *status);
|
extern void do_delete_status(InstanceConfig *instance_config, const char *status);
|
||||||
|
|
||||||
/* in fetch.c */
|
/* in fetch.c */
|
||||||
extern char *slurpFile(const char *datadir,
|
extern char *slurpFile(const char *datadir,
|
||||||
|
36
src/util.c
36
src/util.c
@ -18,6 +18,21 @@
|
|||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
static const char *statusName[] =
|
||||||
|
{
|
||||||
|
"UNKNOWN",
|
||||||
|
"OK",
|
||||||
|
"ERROR",
|
||||||
|
"RUNNING",
|
||||||
|
"MERGING",
|
||||||
|
"MERGED",
|
||||||
|
"DELETING",
|
||||||
|
"DELETED",
|
||||||
|
"DONE",
|
||||||
|
"ORPHAN",
|
||||||
|
"CORRUPT"
|
||||||
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
base36enc(long unsigned int value)
|
base36enc(long unsigned int value)
|
||||||
{
|
{
|
||||||
@ -458,20 +473,6 @@ parse_program_version(const char *program_version)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
static const char *statusName[] =
|
|
||||||
{
|
|
||||||
"UNKNOWN",
|
|
||||||
"OK",
|
|
||||||
"ERROR",
|
|
||||||
"RUNNING",
|
|
||||||
"MERGING",
|
|
||||||
"MERGED",
|
|
||||||
"DELETING",
|
|
||||||
"DELETED",
|
|
||||||
"DONE",
|
|
||||||
"ORPHAN",
|
|
||||||
"CORRUPT"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
status2str(BackupStatus status)
|
status2str(BackupStatus status)
|
||||||
@ -482,16 +483,15 @@ status2str(BackupStatus status)
|
|||||||
return statusName[status];
|
return statusName[status];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BackupStatus
|
BackupStatus
|
||||||
str2status(const char *status)
|
str2status(const char *status)
|
||||||
{
|
{
|
||||||
|
BackupStatus i;
|
||||||
|
|
||||||
for (int i = 0; i <= BACKUP_STATUS_CORRUPT; i++)
|
for (i = BACKUP_STATUS_INVALID; i <= BACKUP_STATUS_CORRUPT; i++)
|
||||||
{
|
{
|
||||||
if (pg_strcasecmp(status, statusName[i]) == 0) return i;
|
if (pg_strcasecmp(status, statusName[i]) == 0) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return BACKUP_STATUS_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -845,6 +845,5 @@ class DeleteTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.assertEqual(show_backups[0]['status'], "OK")
|
self.assertEqual(show_backups[0]['status'], "OK")
|
||||||
self.assertEqual(show_backups[1]['status'], "OK")
|
self.assertEqual(show_backups[1]['status'], "OK")
|
||||||
|
|
||||||
# Clean after yourself
|
# Clean after yourself
|
||||||
self.del_test_dir(module_name, fname)
|
self.del_test_dir(module_name, fname)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user