Skip to content

Commit 3f06d21

Browse files
committed
allow a failed incremental restore to be restarted
1 parent 447f0a6 commit 3f06d21

File tree

3 files changed

+40
-18
lines changed

3 files changed

+40
-18
lines changed

Diff for: src/pg_probackup.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extern const char *PROGRAM_EMAIL;
8484
#define DATABASE_MAP "database_map"
8585
#define HEADER_MAP "page_header_map"
8686
#define HEADER_MAP_TMP "page_header_map_tmp"
87+
#define XLOG_CONTROL_BAK_FILE XLOG_CONTROL_FILE".pbk.bak"
8788

8889
/* Timeout defaults */
8990
#define ARCHIVE_TIMEOUT_DEFAULT 300
@@ -1143,7 +1144,7 @@ extern uint64 get_remote_system_identifier(PGconn *conn);
11431144
extern uint32 get_data_checksum_version(bool safe);
11441145
extern pg_crc32c get_pgcontrol_checksum(const char *pgdata_path);
11451146
extern uint32 get_xlog_seg_size(char *pgdata_path);
1146-
extern void get_redo(const char *pgdata_path, RedoParams *redo);
1147+
extern void get_redo(const char *pgdata_path, const char *pg_control_filename, RedoParams *redo);
11471148
extern void set_min_recovery_point(pgFile *file, const char *backup_path,
11481149
XLogRecPtr stop_backup_lsn);
11491150
extern void copy_pgcontrol_file(const char *from_fullpath, fio_location from_location,

Diff for: src/restore.c

+33-15
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,20 @@ do_restore_or_validate(InstanceState *instanceState, time_t target_backup_id, pg
489489
{
490490
RedoParams redo;
491491
parray *timelines = NULL;
492-
get_redo(instance_config.pgdata, &redo);
492+
493+
/* [Issue #313] check for previous failed incremental restore */
494+
{
495+
char filename[MAXPGPATH];
496+
497+
join_path_components(filename, instance_config.pgdata, XLOG_CONTROL_BAK_FILE);
498+
if (fio_access(filename, F_OK, FIO_DB_HOST) == 0)
499+
{
500+
elog(WARNING, "\"%s\" found, using incremental restore parameters from it", filename);
501+
get_redo(instance_config.pgdata, XLOG_CONTROL_BAK_FILE, &redo);
502+
}
503+
else
504+
get_redo(instance_config.pgdata, XLOG_CONTROL_FILE, &redo);
505+
}
493506

494507
if (redo.checksum_version == 0)
495508
elog(ERROR, "Incremental restore in 'lsn' mode require "
@@ -714,6 +727,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
714727
parray *external_dirs = NULL;
715728
pgFile *dest_pg_control_file = NULL;
716729
char dest_pg_control_fullpath[MAXPGPATH];
730+
char dest_pg_control_bak_fullpath[MAXPGPATH];
717731
/* arrays with meta info for multi threaded backup */
718732
pthread_t *threads;
719733
restore_files_arg *threads_args;
@@ -794,12 +808,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
794808
* unless we are running incremental-lsn restore, then bitmap is mandatory.
795809
*/
796810
if (use_bitmap && parray_num(parent_chain) == 1)
797-
{
798-
if (params->incremental_mode == INCR_NONE)
799-
use_bitmap = false;
800-
else
801-
use_bitmap = true;
802-
}
811+
use_bitmap = params->incremental_mode != INCR_NONE;
803812

804813
/*
805814
* Restore dest_backup internal directories.
@@ -917,6 +926,11 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
917926
pg_strcasecmp(file->name, RELMAPPER_FILENAME) == 0)
918927
redundant = true;
919928

929+
/* global/pg_control.pbk.bak are always keeped, because it's needed for restart failed incremental restore */
930+
if (file->external_dir_num == 0 &&
931+
pg_strcasecmp(file->rel_path, XLOG_CONTROL_BAK_FILE) == 0)
932+
redundant = false;
933+
920934
/* do not delete the useful internal directories */
921935
if (S_ISDIR(file->mode) && !redundant)
922936
continue;
@@ -988,13 +1002,16 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
9881002
elog(ERROR, "File \"%s\" not found in backup %s", XLOG_CONTROL_FILE, base36enc(dest_backup->start_time));
9891003
dest_pg_control_file = parray_remove(dest_files, control_file_elem_index);
9901004

991-
join_path_components(dest_pg_control_fullpath, pgdata_path, dest_pg_control_file->rel_path);
992-
/* remove dest control file before restoring */
993-
if (params->incremental_mode != INCR_NONE)
994-
fio_unlink(dest_pg_control_fullpath, FIO_DB_HOST);
995-
996-
// TODO: maybe we should rename "pg_control" into something like "pg_control.pbk" to
997-
// keep the ability to rerun failed incremental restore ?
1005+
join_path_components(dest_pg_control_fullpath, pgdata_path, XLOG_CONTROL_FILE);
1006+
join_path_components(dest_pg_control_bak_fullpath, pgdata_path, XLOG_CONTROL_BAK_FILE);
1007+
/*
1008+
* rename (if it exist) dest control file before restoring
1009+
* if it doesn't exist, that mean, that we already restoring in a previously failed
1010+
* pgdata, where XLOG_CONTROL_BAK_FILE exist
1011+
*/
1012+
if (params->incremental_mode != INCR_NONE
1013+
&& fio_access(dest_pg_control_fullpath, F_OK, FIO_DB_HOST) == 0)
1014+
fio_rename(dest_pg_control_fullpath, dest_pg_control_bak_fullpath, FIO_DB_HOST);
9981015
}
9991016

10001017
elog(INFO, "Start restoring backup files. PGDATA size: %s", pretty_dest_bytes);
@@ -1042,7 +1059,8 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
10421059
{
10431060
total_bytes += restore_file(dest_pg_control_file, dest_pg_control_fullpath, false, NULL,
10441061
dest_backup, parent_chain, use_bitmap, params->incremental_mode, params->shift_lsn);
1045-
fio_disconnect();
1062+
if (params->incremental_mode != INCR_NONE)
1063+
fio_unlink(dest_pg_control_bak_fullpath, FIO_DB_HOST);
10461064
}
10471065

10481066
time(&end_time);

Diff for: src/util.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -351,15 +351,18 @@ get_pgcontrol_checksum(const char *pgdata_path)
351351
return ControlFile.crc;
352352
}
353353

354+
/*
355+
* you can use XLOG_CONTROL_FILE or XLOG_CONTROL_BAK_FILE for value of control_file_name parameter
356+
*/
354357
void
355-
get_redo(const char *pgdata_path, RedoParams *redo)
358+
get_redo(const char *pgdata_path, const char *pg_control_filename, RedoParams *redo)
356359
{
357360
ControlFileData ControlFile;
358361
char *buffer;
359362
size_t size;
360363

361364
/* First fetch file... */
362-
buffer = slurpFile(pgdata_path, XLOG_CONTROL_FILE, &size, false, FIO_DB_HOST);
365+
buffer = slurpFile(pgdata_path, pg_control_filename, &size, false, FIO_DB_HOST);
363366

364367
digestControlFile(&ControlFile, buffer, size);
365368
pg_free(buffer);

0 commit comments

Comments
 (0)