Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Добавление опции DETACH #405

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -2623,6 +2623,10 @@ readBackupControlFile(const char *path)
backup->status = BACKUP_STATUS_DELETING;
else if (strcmp(status, "DELETED") == 0)
backup->status = BACKUP_STATUS_DELETED;
else if (strcmp(status, "DETACHING") == 0)
backup->status = BACKUP_STATUS_DETACHING;
else if (strcmp(status, "DETACHED") == 0)
backup->status = BACKUP_STATUS_DETACHED;
else if (strcmp(status, "DONE") == 0)
backup->status = BACKUP_STATUS_DONE;
else if (strcmp(status, "ORPHAN") == 0)
Expand Down
159 changes: 159 additions & 0 deletions src/delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,165 @@ do_delete(time_t backup_id)
parray_free(backup_list);
}

void
do_detach(time_t backup_id)
{
int i;
parray *backup_list,
*delete_list;
pgBackup *target_backup = NULL;
size_t size_to_delete = 0;
char size_to_delete_pretty[20];

/* Get complete list of backups */
backup_list = catalog_get_backup_list(instance_name, INVALID_BACKUP_ID);

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++)
{
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);

if (backup->start_time == backup_id)
{
target_backup = backup;
break;
}
}

/* sanity */
if (!target_backup)
elog(ERROR, "Failed to find backup %s, cannot detach", 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, true))
{
parray_append(delete_list, backup);

elog(LOG, "Backup %s %s be detached",
base36enc(backup->start_time), dry_run? "can":"will");

size_to_delete += backup->data_bytes;
if (backup->stream)
size_to_delete += backup->wal_bytes;
}
}

/* Report the resident size to delete */
if (size_to_delete >= 0)
{
pretty_size(size_to_delete, size_to_delete_pretty, lengthof(size_to_delete_pretty));
elog(INFO, "Resident data size to free by detach of backup %s : %s",
base36enc(target_backup->start_time), size_to_delete_pretty);
}

if (!dry_run)
{
/* Lock marked for delete backups */
catalog_lock_backup_list(delete_list, parray_num(delete_list) - 1, 0, false, true);

/* 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 detach backup");

detach_backup_files(backup);
}
}


/* cleanup */
parray_free(delete_list);
parray_walk(backup_list, pgBackupFree);
parray_free(backup_list);
}

/*
* Detach backup files of the backup and update the status of the backup to
* BACKUP_STATUS_DETACHED.
* TODO: delete files on multiple threads
*/
void
detach_backup_files(pgBackup *backup)
{
size_t i;
char timestamp[100];
parray *files;
size_t num_files;
char full_path[MAXPGPATH];

/*
* If the backup was detached already, there is nothing to do.
*/
if (backup->status == BACKUP_STATUS_DETACHED)
{
elog(WARNING, "Backup %s already detached",
base36enc(backup->start_time));
return;
}

if (backup->recovery_time)
time2iso(timestamp, lengthof(timestamp), backup->recovery_time, false);
else
time2iso(timestamp, lengthof(timestamp), backup->start_time, false);

elog(INFO, "Detach: %s %s",
base36enc(backup->start_time), timestamp);
elog(INFO, "Backup paths:\n root_dir = %s\n database_dir = %s\n",
backup->root_dir, backup->database_dir);


/*
* Update STATUS to BACKUP_STATUS_DETACHING in preparation for the case which
* the error occurs before deleting all backup files.
*/
write_backup_status(backup, BACKUP_STATUS_DETACHING, instance_name, false);
elog(INFO, "Set status in control file: DETACHING");

/* list files to be deleted */
files = parray_new();
dir_list_file(files, backup->database_dir, false, false, true, false, false, 0, FIO_BACKUP_HOST);

/* delete leaf node first */
parray_qsort(files, pgFileCompareRelPathWithExternalDesc);
num_files = parray_num(files);
for (i = 0; i < num_files; i++)
{
pgFile *file = (pgFile *) parray_get(files, i);

join_path_components(full_path, backup->database_dir, file->rel_path);

if (interrupted)
elog(ERROR, "interrupted during detach backup");

if (progress)
elog(INFO, "Progress: (%zd/%zd). Delete file \"%s\"",
i + 1, num_files, full_path);

pgFileDelete(file->mode, full_path);
}

parray_walk(files, pgFileFree);
parray_free(files);
backup->status = BACKUP_STATUS_DETACHED;

/* Update STATUS to BACKUP_STATUS_DETACHED */
write_backup_status(backup, BACKUP_STATUS_DETACHED, instance_name, true);
elog(INFO, "Set status in control file: DETACHED");

return;
}


/*
* Merge and purge backups by retention policy. Retention policy is configured by
* retention_redundancy and retention_window variables.
Expand Down
22 changes: 22 additions & 0 deletions src/help.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ static void help_restore(void);
static void help_validate(void);
static void help_show(void);
static void help_delete(void);
static void help_detach(void);
static void help_merge(void);
static void help_set_backup(void);
static void help_set_config(void);
Expand All @@ -40,6 +41,8 @@ help_command(char *command)
help_show();
else if (strcmp(command, "delete") == 0)
help_delete();
else if (strcmp(command, "detach") == 0)
help_detach();
else if (strcmp(command, "merge") == 0)
help_merge();
else if (strcmp(command, "set-backup") == 0)
Expand Down Expand Up @@ -200,6 +203,11 @@ help_pg_probackup(void)
printf(_(" [--dry-run] [--no-validate] [--no-sync]\n"));
printf(_(" [--help]\n"));

printf(_("\n %s detach -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
printf(_(" [-j num-threads] [--progress]\n"));
printf(_(" [-i backup-id]\n"));
printf(_(" [--help]\n"));

printf(_("\n %s merge -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
printf(_(" -i backup-id [--progress] [-j num-threads]\n"));
printf(_(" [--no-validate] [--no-sync]\n"));
Expand Down Expand Up @@ -680,6 +688,20 @@ help_delete(void)
printf(_(" available units: 'ms', 's', 'min', 'h', 'd' (default: min)\n\n"));
}

static void
help_detach(void)
{
printf(_("\n%s detach -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
printf(_(" [-j num-threads] [--progress]\n"));
printf(_(" [-i backup-id ]\n\n"));

printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
printf(_(" --instance=instance_name name of the instance\n"));
printf(_(" -i, --backup-id=backup-id backup to detach\n"));
printf(_(" -j, --threads=NUM number of parallel threads\n"));
printf(_(" --progress show progress\n\n"));
}

static void
help_merge(void)
{
Expand Down
8 changes: 8 additions & 0 deletions src/pg_probackup.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef enum ProbackupSubcmd
RESTORE_CMD,
VALIDATE_CMD,
DELETE_CMD,
DETACH_CMD,
MERGE_CMD,
SHOW_CMD,
SET_CONFIG_CMD,
Expand Down Expand Up @@ -334,6 +335,8 @@ main(int argc, char *argv[])
backup_subcmd = VALIDATE_CMD;
else if (strcmp(argv[1], "delete") == 0)
backup_subcmd = DELETE_CMD;
else if (strcmp(argv[1], "detach") == 0)
backup_subcmd = DETACH_CMD;
else if (strcmp(argv[1], "merge") == 0)
backup_subcmd = MERGE_CMD;
else if (strcmp(argv[1], "show") == 0)
Expand Down Expand Up @@ -405,6 +408,7 @@ main(int argc, char *argv[])
backup_subcmd == RESTORE_CMD ||
backup_subcmd == VALIDATE_CMD ||
backup_subcmd == DELETE_CMD ||
backup_subcmd == DETACH_CMD ||
backup_subcmd == MERGE_CMD ||
backup_subcmd == SET_CONFIG_CMD ||
backup_subcmd == SET_BACKUP_CMD)
Expand Down Expand Up @@ -663,6 +667,7 @@ main(int argc, char *argv[])
if (backup_subcmd != RESTORE_CMD &&
backup_subcmd != VALIDATE_CMD &&
backup_subcmd != DELETE_CMD &&
backup_subcmd != DETACH_CMD &&
backup_subcmd != MERGE_CMD &&
backup_subcmd != SET_BACKUP_CMD &&
backup_subcmd != SHOW_CMD)
Expand Down Expand Up @@ -850,6 +855,9 @@ main(int argc, char *argv[])
else
do_delete(current.backup_id);
break;
case DETACH_CMD:
do_detach(current.backup_id);
break;
case MERGE_CMD:
do_merge(current.backup_id, no_validate, no_sync);
break;
Expand Down
6 changes: 5 additions & 1 deletion src/pg_probackup.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,9 @@ typedef enum BackupStatus
BACKUP_STATUS_DELETED, /* data files have been deleted */
BACKUP_STATUS_DONE, /* completed but not validated yet */
BACKUP_STATUS_ORPHAN, /* backup validity is unknown but at least one parent backup is corrupted */
BACKUP_STATUS_CORRUPT /* files are corrupted, not available */
BACKUP_STATUS_DETACHING, /* data files are being detached */
BACKUP_STATUS_DETACHED, /* data files have been detached */
BACKUP_STATUS_CORRUPT /* files are corrupted, not available */
} BackupStatus;

typedef enum BackupMode
Expand Down Expand Up @@ -869,6 +871,8 @@ extern int do_show(const char *instance_name, time_t requested_backup_id, bool s
/* in delete.c */
extern void do_delete(time_t backup_id);
extern void delete_backup_files(pgBackup *backup);
extern void do_detach(time_t backup_id);
extern void detach_backup_files(pgBackup *backup);
extern void do_retention(bool no_validate, bool no_sync);
extern int do_delete_instance(void);
extern void do_delete_status(InstanceConfig *instance_config, const char *status);
Expand Down
2 changes: 2 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ static const char *statusName[] =
"DELETED",
"DONE",
"ORPHAN",
"DETACHING",
"DETACHED",
"CORRUPT"
};

Expand Down