Skip to content

Commit 2479595

Browse files
authored
Add files via upload
1 parent b395b3c commit 2479595

File tree

6 files changed

+200
-1
lines changed

6 files changed

+200
-1
lines changed

src/catalog.c

+4
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,10 @@ readBackupControlFile(const char *path)
26232623
backup->status = BACKUP_STATUS_DELETING;
26242624
else if (strcmp(status, "DELETED") == 0)
26252625
backup->status = BACKUP_STATUS_DELETED;
2626+
else if (strcmp(status, "DETACHING") == 0)
2627+
backup->status = BACKUP_STATUS_DETACHING;
2628+
else if (strcmp(status, "DETACHED") == 0)
2629+
backup->status = BACKUP_STATUS_DETACHED;
26262630
else if (strcmp(status, "DONE") == 0)
26272631
backup->status = BACKUP_STATUS_DONE;
26282632
else if (strcmp(status, "ORPHAN") == 0)

src/delete.c

+159
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,165 @@ do_delete(time_t backup_id)
113113
parray_free(backup_list);
114114
}
115115

116+
void
117+
do_detach(time_t backup_id)
118+
{
119+
int i;
120+
parray *backup_list,
121+
*delete_list;
122+
pgBackup *target_backup = NULL;
123+
size_t size_to_delete = 0;
124+
char size_to_delete_pretty[20];
125+
126+
/* Get complete list of backups */
127+
backup_list = catalog_get_backup_list(instance_name, INVALID_BACKUP_ID);
128+
129+
delete_list = parray_new();
130+
131+
/* Find backup to be deleted and make increment backups array to be deleted */
132+
for (i = 0; i < parray_num(backup_list); i++)
133+
{
134+
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
135+
136+
if (backup->start_time == backup_id)
137+
{
138+
target_backup = backup;
139+
break;
140+
}
141+
}
142+
143+
/* sanity */
144+
if (!target_backup)
145+
elog(ERROR, "Failed to find backup %s, cannot detach", base36enc(backup_id));
146+
147+
/* form delete list */
148+
for (i = 0; i < parray_num(backup_list); i++)
149+
{
150+
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
151+
152+
/* check if backup is descendant of delete target */
153+
if (is_parent(target_backup->start_time, backup, true))
154+
{
155+
parray_append(delete_list, backup);
156+
157+
elog(LOG, "Backup %s %s be detached",
158+
base36enc(backup->start_time), dry_run? "can":"will");
159+
160+
size_to_delete += backup->data_bytes;
161+
if (backup->stream)
162+
size_to_delete += backup->wal_bytes;
163+
}
164+
}
165+
166+
/* Report the resident size to delete */
167+
if (size_to_delete >= 0)
168+
{
169+
pretty_size(size_to_delete, size_to_delete_pretty, lengthof(size_to_delete_pretty));
170+
elog(INFO, "Resident data size to free by detach of backup %s : %s",
171+
base36enc(target_backup->start_time), size_to_delete_pretty);
172+
}
173+
174+
if (!dry_run)
175+
{
176+
/* Lock marked for delete backups */
177+
catalog_lock_backup_list(delete_list, parray_num(delete_list) - 1, 0, false, true);
178+
179+
/* Delete backups from the end of list */
180+
for (i = (int) parray_num(delete_list) - 1; i >= 0; i--)
181+
{
182+
pgBackup *backup = (pgBackup *) parray_get(delete_list, (size_t) i);
183+
184+
if (interrupted)
185+
elog(ERROR, "interrupted during detach backup");
186+
187+
detach_backup_files(backup);
188+
}
189+
}
190+
191+
192+
/* cleanup */
193+
parray_free(delete_list);
194+
parray_walk(backup_list, pgBackupFree);
195+
parray_free(backup_list);
196+
}
197+
198+
/*
199+
* Detach backup files of the backup and update the status of the backup to
200+
* BACKUP_STATUS_DETACHED.
201+
* TODO: delete files on multiple threads
202+
*/
203+
void
204+
detach_backup_files(pgBackup *backup)
205+
{
206+
size_t i;
207+
char timestamp[100];
208+
parray *files;
209+
size_t num_files;
210+
char full_path[MAXPGPATH];
211+
212+
/*
213+
* If the backup was detached already, there is nothing to do.
214+
*/
215+
if (backup->status == BACKUP_STATUS_DETACHED)
216+
{
217+
elog(WARNING, "Backup %s already detached",
218+
base36enc(backup->start_time));
219+
return;
220+
}
221+
222+
if (backup->recovery_time)
223+
time2iso(timestamp, lengthof(timestamp), backup->recovery_time, false);
224+
else
225+
time2iso(timestamp, lengthof(timestamp), backup->start_time, false);
226+
227+
elog(INFO, "Detach: %s %s",
228+
base36enc(backup->start_time), timestamp);
229+
elog(INFO, "Backup paths:\n root_dir = %s\n database_dir = %s\n",
230+
backup->root_dir, backup->database_dir);
231+
232+
233+
/*
234+
* Update STATUS to BACKUP_STATUS_DETACHING in preparation for the case which
235+
* the error occurs before deleting all backup files.
236+
*/
237+
write_backup_status(backup, BACKUP_STATUS_DETACHING, instance_name, false);
238+
elog(INFO, "Set status in control file: DETACHING");
239+
240+
/* list files to be deleted */
241+
files = parray_new();
242+
dir_list_file(files, backup->database_dir, false, false, true, false, false, 0, FIO_BACKUP_HOST);
243+
244+
/* delete leaf node first */
245+
parray_qsort(files, pgFileCompareRelPathWithExternalDesc);
246+
num_files = parray_num(files);
247+
for (i = 0; i < num_files; i++)
248+
{
249+
pgFile *file = (pgFile *) parray_get(files, i);
250+
251+
join_path_components(full_path, backup->database_dir, file->rel_path);
252+
253+
if (interrupted)
254+
elog(ERROR, "interrupted during detach backup");
255+
256+
if (progress)
257+
elog(INFO, "Progress: (%zd/%zd). Delete file \"%s\"",
258+
i + 1, num_files, full_path);
259+
260+
pgFileDelete(file->mode, full_path);
261+
}
262+
263+
parray_walk(files, pgFileFree);
264+
parray_free(files);
265+
backup->status = BACKUP_STATUS_DETACHED;
266+
267+
/* Update STATUS to BACKUP_STATUS_DETACHED */
268+
write_backup_status(backup, BACKUP_STATUS_DETACHED, instance_name, true);
269+
elog(INFO, "Set status in control file: DETACHED");
270+
271+
return;
272+
}
273+
274+
116275
/*
117276
* Merge and purge backups by retention policy. Retention policy is configured by
118277
* retention_redundancy and retention_window variables.

src/help.c

+22
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ static void help_restore(void);
1515
static void help_validate(void);
1616
static void help_show(void);
1717
static void help_delete(void);
18+
static void help_detach(void);
1819
static void help_merge(void);
1920
static void help_set_backup(void);
2021
static void help_set_config(void);
@@ -40,6 +41,8 @@ help_command(char *command)
4041
help_show();
4142
else if (strcmp(command, "delete") == 0)
4243
help_delete();
44+
else if (strcmp(command, "detach") == 0)
45+
help_detach();
4346
else if (strcmp(command, "merge") == 0)
4447
help_merge();
4548
else if (strcmp(command, "set-backup") == 0)
@@ -200,6 +203,11 @@ help_pg_probackup(void)
200203
printf(_(" [--dry-run] [--no-validate] [--no-sync]\n"));
201204
printf(_(" [--help]\n"));
202205

206+
printf(_("\n %s detach -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
207+
printf(_(" [-j num-threads] [--progress]\n"));
208+
printf(_(" [-i backup-id]\n"));
209+
printf(_(" [--help]\n"));
210+
203211
printf(_("\n %s merge -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
204212
printf(_(" -i backup-id [--progress] [-j num-threads]\n"));
205213
printf(_(" [--no-validate] [--no-sync]\n"));
@@ -680,6 +688,20 @@ help_delete(void)
680688
printf(_(" available units: 'ms', 's', 'min', 'h', 'd' (default: min)\n\n"));
681689
}
682690

691+
static void
692+
help_detach(void)
693+
{
694+
printf(_("\n%s detach -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
695+
printf(_(" [-j num-threads] [--progress]\n"));
696+
printf(_(" [-i backup-id ]\n\n"));
697+
698+
printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
699+
printf(_(" --instance=instance_name name of the instance\n"));
700+
printf(_(" -i, --backup-id=backup-id backup to detach\n"));
701+
printf(_(" -j, --threads=NUM number of parallel threads\n"));
702+
printf(_(" --progress show progress\n\n"));
703+
}
704+
683705
static void
684706
help_merge(void)
685707
{

src/pg_probackup.c

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typedef enum ProbackupSubcmd
3939
RESTORE_CMD,
4040
VALIDATE_CMD,
4141
DELETE_CMD,
42+
DETACH_CMD,
4243
MERGE_CMD,
4344
SHOW_CMD,
4445
SET_CONFIG_CMD,
@@ -334,6 +335,8 @@ main(int argc, char *argv[])
334335
backup_subcmd = VALIDATE_CMD;
335336
else if (strcmp(argv[1], "delete") == 0)
336337
backup_subcmd = DELETE_CMD;
338+
else if (strcmp(argv[1], "detach") == 0)
339+
backup_subcmd = DETACH_CMD;
337340
else if (strcmp(argv[1], "merge") == 0)
338341
backup_subcmd = MERGE_CMD;
339342
else if (strcmp(argv[1], "show") == 0)
@@ -405,6 +408,7 @@ main(int argc, char *argv[])
405408
backup_subcmd == RESTORE_CMD ||
406409
backup_subcmd == VALIDATE_CMD ||
407410
backup_subcmd == DELETE_CMD ||
411+
backup_subcmd == DETACH_CMD ||
408412
backup_subcmd == MERGE_CMD ||
409413
backup_subcmd == SET_CONFIG_CMD ||
410414
backup_subcmd == SET_BACKUP_CMD)
@@ -663,6 +667,7 @@ main(int argc, char *argv[])
663667
if (backup_subcmd != RESTORE_CMD &&
664668
backup_subcmd != VALIDATE_CMD &&
665669
backup_subcmd != DELETE_CMD &&
670+
backup_subcmd != DETACH_CMD &&
666671
backup_subcmd != MERGE_CMD &&
667672
backup_subcmd != SET_BACKUP_CMD &&
668673
backup_subcmd != SHOW_CMD)
@@ -850,6 +855,9 @@ main(int argc, char *argv[])
850855
else
851856
do_delete(current.backup_id);
852857
break;
858+
case DETACH_CMD:
859+
do_detach(current.backup_id);
860+
break;
853861
case MERGE_CMD:
854862
do_merge(current.backup_id, no_validate, no_sync);
855863
break;

src/pg_probackup.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,9 @@ typedef enum BackupStatus
284284
BACKUP_STATUS_DELETED, /* data files have been deleted */
285285
BACKUP_STATUS_DONE, /* completed but not validated yet */
286286
BACKUP_STATUS_ORPHAN, /* backup validity is unknown but at least one parent backup is corrupted */
287-
BACKUP_STATUS_CORRUPT /* files are corrupted, not available */
287+
BACKUP_STATUS_DETACHING, /* data files are being detached */
288+
BACKUP_STATUS_DETACHED, /* data files have been detached */
289+
BACKUP_STATUS_CORRUPT /* files are corrupted, not available */
288290
} BackupStatus;
289291

290292
typedef enum BackupMode
@@ -869,6 +871,8 @@ extern int do_show(const char *instance_name, time_t requested_backup_id, bool s
869871
/* in delete.c */
870872
extern void do_delete(time_t backup_id);
871873
extern void delete_backup_files(pgBackup *backup);
874+
extern void do_detach(time_t backup_id);
875+
extern void detach_backup_files(pgBackup *backup);
872876
extern void do_retention(bool no_validate, bool no_sync);
873877
extern int do_delete_instance(void);
874878
extern void do_delete_status(InstanceConfig *instance_config, const char *status);

src/util.c

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ static const char *statusName[] =
3030
"DELETED",
3131
"DONE",
3232
"ORPHAN",
33+
"DETACHING",
34+
"DETACHED",
3335
"CORRUPT"
3436
};
3537

0 commit comments

Comments
 (0)