@@ -29,9 +29,8 @@ typedef struct
29
29
const char * to_root ;
30
30
size_t restored_bytes ;
31
31
bool use_bitmap ;
32
- bool incremental ;
33
- bool incremental_lsn ;
34
- XLogRecPtr horizonLsn ;
32
+ IncrRestoreMode incremental_mode ;
33
+ XLogRecPtr shift_lsn ; /* used only in LSN incremental_mode */
35
34
36
35
/*
37
36
* Return value from the thread.
@@ -52,7 +51,7 @@ static void restore_chain(pgBackup *dest_backup, parray *parent_chain,
52
51
parray * dbOid_exclude_list , pgRestoreParams * params ,
53
52
const char * pgdata_path , bool no_sync );
54
53
static void check_incremental_compatibility (const char * pgdata , uint64 system_identifier ,
55
- bool incremental_lsn );
54
+ IncrRestoreMode incremental_mode );
56
55
57
56
/*
58
57
* Iterate over backup list to find all ancestors of the broken parent_backup
@@ -117,7 +116,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
117
116
parray * dbOid_exclude_list = NULL ;
118
117
bool pgdata_is_empty = true;
119
118
bool tblspaces_are_empty = true;
120
- XLogRecPtr horizonLsn = InvalidXLogRecPtr ;
119
+ XLogRecPtr shift_lsn = InvalidXLogRecPtr ;
121
120
122
121
if (params -> is_restore )
123
122
{
@@ -128,14 +127,14 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
128
127
if (!dir_is_empty (instance_config .pgdata , FIO_DB_HOST ))
129
128
{
130
129
/* Check that remote system is NOT running and systemd id is the same as ours */
131
- if (params -> incremental )
130
+ if (params -> incremental_mode != INCR_NONE )
132
131
{
133
132
elog (INFO , "Running incremental restore into nonempty directory: \"%s\"" ,
134
133
instance_config .pgdata );
135
134
136
135
check_incremental_compatibility (instance_config .pgdata ,
137
136
instance_config .system_identifier ,
138
- params -> incremental_lsn );
137
+ params -> incremental_mode );
139
138
}
140
139
else
141
140
elog (ERROR , "Restore destination is not empty: \"%s\"" ,
@@ -328,13 +327,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
328
327
base36enc (dest_backup -> start_time ));
329
328
}
330
329
331
- /*
332
- * We have found full backup by link,
333
- * now we need to walk the list to find its index.
334
- *
335
- * TODO I think we should rewrite it someday to use double linked list
336
- * and avoid relying on sort order anymore.
337
- */
330
+ /* We have found full backup */
338
331
base_full_backup = tmp_backup ;
339
332
}
340
333
@@ -347,14 +340,18 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
347
340
*/
348
341
if (params -> is_restore )
349
342
{
350
- check_tablespace_mapping (dest_backup , params -> incremental , & tblspaces_are_empty );
343
+ check_tablespace_mapping (dest_backup , params -> incremental_mode != INCR_NONE , & tblspaces_are_empty );
351
344
352
345
if (pgdata_is_empty && tblspaces_are_empty )
353
- params -> incremental = false;
346
+ {
347
+ elog (INFO , "Destination directory and tablespace directories are empty, "
348
+ "disabled incremental restore" );
349
+ params -> incremental_mode = INCR_NONE ;
350
+ }
354
351
355
352
/* no point in checking external directories if their restore is not requested */
356
353
if (!params -> skip_external_dirs )
357
- check_external_dir_mapping (dest_backup , params -> incremental );
354
+ check_external_dir_mapping (dest_backup , params -> incremental_mode != INCR_NONE );
358
355
}
359
356
360
357
/* At this point we are sure that parent chain is whole
@@ -387,7 +384,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
387
384
* F - destination backup
388
385
* * - switch point
389
386
*
390
- * When running incremental restore in shift mode, we get a bitmap of pages,
387
+ * When running incremental restore in 'lsn' mode, we get a bitmap of pages,
391
388
* whose LSN is less than shift-LSN (backup C stop_lsn).
392
389
* So when restoring file, we can skip restore of pages coming from
393
390
* A, B and C.
@@ -408,7 +405,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
408
405
* We must be able to differentiate the scenario A and scenario B.
409
406
*
410
407
*/
411
- if (params -> is_restore && params -> incremental && params -> incremental_lsn )
408
+ if (params -> is_restore && params -> incremental_mode == INCR_LSN )
412
409
{
413
410
RedoParams redo ;
414
411
parray * timelines = NULL ;
@@ -418,7 +415,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
418
415
419
416
if (!timelines )
420
417
elog (WARNING , "Failed to get history for redo timeline %i, "
421
- "multi-timeline incremental restore in shift mode is impossible" , redo .tli );
418
+ "multi-timeline incremental restore in 'lsn' mode is impossible" , redo .tli );
422
419
423
420
tmp_backup = dest_backup ;
424
421
@@ -432,17 +429,17 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
432
429
*/
433
430
if (redo .tli == tmp_backup -> tli )
434
431
{
435
- elog (INFO , "Backup %s is chosen as shiftpoint" ,
432
+ elog (INFO , "Backup %s is chosen as shiftpoint, its Stop LSN will be used as shift LSN " ,
436
433
base36enc (tmp_backup -> start_time ));
437
434
438
- horizonLsn = tmp_backup -> stop_lsn ;
435
+ shift_lsn = tmp_backup -> stop_lsn ;
439
436
break ;
440
437
}
441
438
442
439
if (!timelines )
443
440
{
444
441
elog (WARNING , "Redo timeline %i differs from target timeline %i, "
445
- "in this case, to safely run incremental restore in shift mode, "
442
+ "in this case, to safely run incremental restore in 'lsn' mode, "
446
443
"the history file for timeline %i is mandatory" ,
447
444
redo .tli , tmp_backup -> tli , redo .tli );
448
445
break ;
@@ -451,7 +448,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
451
448
/* check whether the candidate tli is a part of redo TLI history */
452
449
if (tliIsPartOfHistory (timelines , tmp_backup -> tli ))
453
450
{
454
- horizonLsn = tmp_backup -> stop_lsn ;
451
+ shift_lsn = tmp_backup -> stop_lsn ;
455
452
break ;
456
453
}
457
454
else
@@ -463,23 +460,23 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
463
460
tmp_backup = tmp_backup -> parent_backup_link ;
464
461
}
465
462
466
- if (XLogRecPtrIsInvalid (horizonLsn ))
467
- elog (ERROR , "Cannot perform incremental restore of backup chain %s in shift mode, "
463
+ if (XLogRecPtrIsInvalid (shift_lsn ))
464
+ elog (ERROR , "Cannot perform incremental restore of backup chain %s in 'lsn' mode, "
468
465
"because destination directory redo point %X/%X on tli %i is out of reach" ,
469
466
base36enc (dest_backup -> start_time ),
470
467
(uint32 ) (redo .lsn >> 32 ), (uint32 ) redo .lsn , redo .tli );
471
468
else
472
469
elog (INFO , "Destination directory redo point %X/%X on tli %i is within reach of "
473
- "backup %s with STOP LSN %X/%X on tli %i, incremental restore in shift mode is possible" ,
470
+ "backup %s with Stop LSN %X/%X on tli %i, incremental restore in 'lsn' mode is possible" ,
474
471
(uint32 ) (redo .lsn >> 32 ), (uint32 ) redo .lsn , redo .tli ,
475
472
base36enc (tmp_backup -> start_time ),
476
473
(uint32 ) (tmp_backup -> stop_lsn >> 32 ), (uint32 ) tmp_backup -> stop_lsn ,
477
474
tmp_backup -> tli );
478
475
479
476
elog (INFO , "shift LSN: %X/%X" ,
480
- (uint32 ) (horizonLsn >> 32 ), (uint32 ) horizonLsn );
477
+ (uint32 ) (shift_lsn >> 32 ), (uint32 ) shift_lsn );
481
478
482
- params -> horizonLsn = horizonLsn ;
479
+ params -> shift_lsn = shift_lsn ;
483
480
}
484
481
485
482
/* for validation or restore with enabled validation */
@@ -706,7 +703,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
706
703
{
707
704
use_bitmap = false;
708
705
709
- if (params -> incremental )
706
+ if (params -> incremental_mode != INCR_NONE )
710
707
elog (ERROR , "incremental restore is not possible for backups older than 2.3.0 version" );
711
708
}
712
709
@@ -715,7 +712,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
715
712
*/
716
713
if (use_bitmap && parray_num (parent_chain ) == 1 )
717
714
{
718
- if (params -> incremental && params -> incremental_lsn )
715
+ if (params -> incremental_mode == INCR_NONE )
719
716
use_bitmap = true;
720
717
else
721
718
use_bitmap = false;
@@ -726,7 +723,8 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
726
723
*/
727
724
create_data_directories (dest_files , instance_config .pgdata ,
728
725
dest_backup -> root_dir , true,
729
- params -> incremental , FIO_DB_HOST );
726
+ params -> incremental_mode != INCR_NONE ,
727
+ FIO_DB_HOST );
730
728
731
729
/*
732
730
* Restore dest_backup external directories.
@@ -777,7 +775,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
777
775
}
778
776
779
777
/* Get list of files in destination directory and remove redundant files */
780
- if (params -> incremental )
778
+ if (params -> incremental_mode != INCR_NONE )
781
779
{
782
780
pgdata_files = parray_new ();
783
781
@@ -883,9 +881,8 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
883
881
arg -> skip_external_dirs = params -> skip_external_dirs ;
884
882
arg -> to_root = pgdata_path ;
885
883
arg -> use_bitmap = use_bitmap ;
886
- arg -> incremental = params -> incremental ;
887
- arg -> incremental_lsn = params -> incremental_lsn ;
888
- arg -> horizonLsn = params -> horizonLsn ;
884
+ arg -> incremental_mode = params -> incremental_mode ;
885
+ arg -> shift_lsn = params -> shift_lsn ;
889
886
threads_args [i ].restored_bytes = 0 ;
890
887
/* By default there are some error */
891
888
threads_args [i ].ret = 1 ;
@@ -1080,7 +1077,7 @@ restore_files(void *arg)
1080
1077
join_path_components (to_fullpath , external_path , dest_file -> rel_path );
1081
1078
}
1082
1079
1083
- if (arguments -> incremental &&
1080
+ if (arguments -> incremental_mode != INCR_NONE &&
1084
1081
parray_bsearch (arguments -> pgdata_files , dest_file , pgFileCompareRelPathWithExternalDesc ))
1085
1082
{
1086
1083
already_exists = true;
@@ -1096,14 +1093,13 @@ restore_files(void *arg)
1096
1093
dest_file -> is_datafile && !dest_file -> is_cfs &&
1097
1094
dest_file -> n_blocks > 0 )
1098
1095
{
1099
- if (arguments -> incremental_lsn )
1096
+ if (arguments -> incremental_mode == INCR_LSN )
1100
1097
{
1101
- /* TODO: return lsn_map */
1102
1098
lsn_map = fio_get_lsn_map (to_fullpath , arguments -> dest_backup -> checksum_version ,
1103
- dest_file -> n_blocks , arguments -> horizonLsn ,
1099
+ dest_file -> n_blocks , arguments -> shift_lsn ,
1104
1100
dest_file -> segno * RELSEG_SIZE , FIO_DB_HOST );
1105
1101
}
1106
- else
1102
+ else if ( arguments -> incremental_mode == INCR_CHECKSUM )
1107
1103
{
1108
1104
checksum_map = fio_get_checksum_map (to_fullpath , arguments -> dest_backup -> checksum_version ,
1109
1105
dest_file -> n_blocks , arguments -> dest_backup -> stop_lsn ,
@@ -1144,7 +1140,7 @@ restore_files(void *arg)
1144
1140
arguments -> restored_bytes += restore_data_file (arguments -> parent_chain ,
1145
1141
dest_file , out , to_fullpath ,
1146
1142
arguments -> use_bitmap , checksum_map ,
1147
- arguments -> horizonLsn , lsn_map );
1143
+ arguments -> shift_lsn , lsn_map );
1148
1144
}
1149
1145
else
1150
1146
{
@@ -1943,7 +1939,8 @@ get_dbOid_exclude_list(pgBackup *backup, parray *datname_list,
1943
1939
* Depending on type of incremental restore requirements are differs.
1944
1940
*/
1945
1941
void
1946
- check_incremental_compatibility (const char * pgdata , uint64 system_identifier , bool incremental_lsn )
1942
+ check_incremental_compatibility (const char * pgdata , uint64 system_identifier ,
1943
+ IncrRestoreMode incremental_mode )
1947
1944
{
1948
1945
uint64 system_id_pgdata ;
1949
1946
bool success = true;
@@ -1993,16 +1990,16 @@ check_incremental_compatibility(const char *pgdata, uint64 system_identifier, bo
1993
1990
* TODO: maybe there should be some other signs, pointing to pg_control
1994
1991
* desynchronization with cluster state.
1995
1992
*/
1996
- if (incremental_lsn )
1993
+ if (incremental_mode == INCR_LSN )
1997
1994
{
1998
1995
snprintf (backup_label , MAXPGPATH , "%s/backup_label" , pgdata );
1999
1996
if (fio_access (backup_label , F_OK , FIO_DB_HOST ) == 0 )
2000
1997
{
2001
1998
elog (WARNING , "Destination directory contains \"backup_control\" file. "
2002
1999
"This does NOT mean that you should delete this file and retry, only that "
2003
- "lsn-based incremental restore can corrupt data , when applied to instance "
2004
- "with pg_control not synchronized with cluster state."
2005
- "Consider to use checksum-based incremental restore. " );
2000
+ "incremental restore in 'lsn' mode can produce incorrect result , when applied "
2001
+ "to cluster with pg_control not synchronized with cluster state."
2002
+ "Consider to use incremental restore in 'checksum' mode " );
2006
2003
success = false;
2007
2004
}
2008
2005
}
0 commit comments