From d48f4024a8d775a2a3ca7884ffddfd9ae420816b Mon Sep 17 00:00:00 2001 From: Grigory Smolkin Date: Thu, 28 Mar 2019 17:19:33 +0300 Subject: [PATCH] PGPRO-2589: use parent_link when deleting backup chain via delete -i BACKUP_ID --- src/delete.c | 95 ++++++++++++++++++++++--------------------------- tests/delete.py | 20 ----------- 2 files changed, 42 insertions(+), 73 deletions(-) diff --git a/src/delete.c b/src/delete.c index 287e7377..2b2f0d61 100644 --- a/src/delete.c +++ b/src/delete.c @@ -24,71 +24,57 @@ do_delete(time_t backup_id) parray *backup_list, *delete_list; pgBackup *target_backup = NULL; - time_t parent_id = 0; XLogRecPtr oldest_lsn = InvalidXLogRecPtr; TimeLineID oldest_tli = 0; /* Get complete list of backups */ backup_list = catalog_get_backup_list(INVALID_BACKUP_ID); - if (backup_id != 0) + delete_list = parray_new(); + + /* Find backup to be deleted and make increment backups array to be deleted */ + for (i = 0; i < parray_num(backup_list); i++) { - delete_list = parray_new(); + pgBackup *backup = (pgBackup *) parray_get(backup_list, i); - /* Find backup to be deleted and make increment backups array to be deleted */ - for (i = (int) parray_num(backup_list) - 1; i >= 0; i--) + if (backup->start_time == backup_id) { - pgBackup *backup = (pgBackup *) parray_get(backup_list, (size_t) i); - - if (backup->start_time == backup_id) - { - parray_append(delete_list, backup); - - /* - * Do not remove next backups, if target backup was finished - * incorrectly. - */ - if (backup->status == BACKUP_STATUS_ERROR) - break; - - /* Save backup id to retreive increment backups */ - parent_id = backup->start_time; - target_backup = backup; - } - else if (target_backup) - { - if (backup->backup_mode != BACKUP_MODE_FULL && - backup->parent_backup == parent_id) - { - /* Append to delete list increment backup */ - parray_append(delete_list, backup); - /* Save backup id to retreive increment backups */ - parent_id = backup->start_time; - } - else - break; - } + target_backup = backup; + break; } - - if (parray_num(delete_list) == 0) - elog(ERROR, "no backup found, cannot delete"); - - catalog_lock_backup_list(delete_list, parray_num(delete_list) - 1, 0); - - /* Delete backups from the end of list */ - for (i = (int) parray_num(delete_list) - 1; i >= 0; i--) - { - pgBackup *backup = (pgBackup *) parray_get(delete_list, (size_t) i); - - if (interrupted) - elog(ERROR, "interrupted during delete backup"); - - delete_backup_files(backup); - } - - parray_free(delete_list); } + /* sanity */ + if (!target_backup) + elog(ERROR, "Failed to find backup %s, cannot delete", base36enc(backup_id)); + + /* form delete list */ + for (i = 0; i < parray_num(backup_list); i++) + { + pgBackup *backup = (pgBackup *) parray_get(backup_list, i); + + /* check if backup is descendant of delete target */ + if (is_parent(target_backup->start_time, backup, false)) + parray_append(delete_list, backup); + } + parray_append(delete_list, target_backup); + + /* Lock marked for delete backups */ + catalog_lock_backup_list(delete_list, parray_num(delete_list) - 1, 0); + + /* Delete backups from the end of list */ + for (i = (int) parray_num(delete_list) - 1; i >= 0; i--) + { + pgBackup *backup = (pgBackup *) parray_get(delete_list, (size_t) i); + + if (interrupted) + elog(ERROR, "interrupted during delete backup"); + + delete_backup_files(backup); + } + + parray_free(delete_list); + /* Clean WAL segments */ if (delete_wal) { @@ -303,6 +289,9 @@ delete_backup_files(pgBackup *backup) elog(INFO, "Progress: (%zd/%zd). Process file \"%s\"", i + 1, num_files, file->path); + if (interrupted) + elog(ERROR, "interrupted during delete backup"); + pgFileDelete(file); } diff --git a/tests/delete.py b/tests/delete.py index 3c573a85..71919c86 100644 --- a/tests/delete.py +++ b/tests/delete.py @@ -388,16 +388,10 @@ class DeleteTest(ProbackupTest, unittest.TestCase): self.set_archiving(backup_dir, 'node', node) node.slow_start() - node.pgbench_init(scale=3) - # Take FULL BACKUPs backup_id_a = self.backup_node(backup_dir, 'node', node) - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() backup_id_b = self.backup_node(backup_dir, 'node', node) - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() # Change FULLb backup status to ERROR self.change_backup_status(backup_dir, 'node', backup_id_b, 'ERROR') @@ -405,9 +399,6 @@ class DeleteTest(ProbackupTest, unittest.TestCase): page_id_a1 = self.backup_node( backup_dir, 'node', node, backup_type='page') - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() - # Change FULLb backup status to OK self.change_backup_status(backup_dir, 'node', backup_id_b, 'OK') @@ -426,9 +417,6 @@ class DeleteTest(ProbackupTest, unittest.TestCase): # FULLb OK # FULLa OK - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() - # Change PAGEa1 backup status to OK self.change_backup_status(backup_dir, 'node', page_id_a1, 'OK') @@ -443,9 +431,6 @@ class DeleteTest(ProbackupTest, unittest.TestCase): page_id_a2 = self.backup_node( backup_dir, 'node', node, backup_type='page') - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() - # PAGEa2 OK # PAGEb1 ERROR # PAGEa1 OK @@ -467,9 +452,6 @@ class DeleteTest(ProbackupTest, unittest.TestCase): page_id_b2 = self.backup_node( backup_dir, 'node', node, backup_type='page') - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() - # PAGEb2 OK # PAGEa2 ERROR # PAGEb1 OK @@ -490,8 +472,6 @@ class DeleteTest(ProbackupTest, unittest.TestCase): page_id_a3 = self.backup_node( backup_dir, 'node', node, backup_type='page') - pgbench = node.pgbench(options=['-T', '10', '-c', '2']) - pgbench.wait() # PAGEa3 OK # PAGEb2 ERROR