@@ -49,6 +49,8 @@ static void pg12_recovery_config(pgBackup *backup, bool add_include);
49
49
static void restore_chain (pgBackup * dest_backup , parray * parent_chain ,
50
50
parray * dbOid_exclude_list , pgRestoreParams * params ,
51
51
const char * pgdata_path , bool no_sync );
52
+ static void check_incremental_compatibility (const char * pgdata , uint64 system_identifier ,
53
+ bool lsn_based );
52
54
53
55
/*
54
56
* Iterate over backup list to find all ancestors of the broken parent_backup
@@ -111,6 +113,8 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
111
113
char * action = params -> is_restore ? "Restore" :"Validate" ;
112
114
parray * parent_chain = NULL ;
113
115
parray * dbOid_exclude_list = NULL ;
116
+ bool pgdata_is_empty = true;
117
+ bool tblspaces_are_empty = true;
114
118
115
119
if (params -> is_restore )
116
120
{
@@ -126,16 +130,17 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
126
130
{
127
131
elog (INFO , "Running incremental restore into nonempty directory: \"%s\"" ,
128
132
instance_config .pgdata );
133
+
134
+ check_incremental_compatibility (instance_config .pgdata ,
135
+ instance_config .system_identifier ,
136
+ false);
129
137
}
130
138
else
131
139
elog (ERROR , "Restore destination is not empty: \"%s\"" ,
132
140
instance_config .pgdata );
133
- }
134
- else
135
- {
136
- /* if remote directory is empty then disable incremental restore */
137
- if (params -> incremental )
138
- params -> incremental = false;
141
+
142
+ /* if remote directory is empty then incremental restore may be disabled */
143
+ pgdata_is_empty = true;
139
144
}
140
145
}
141
146
@@ -340,7 +345,10 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
340
345
*/
341
346
if (params -> is_restore )
342
347
{
343
- check_tablespace_mapping (dest_backup );
348
+ check_tablespace_mapping (dest_backup , params -> incremental , & tblspaces_are_empty );
349
+
350
+ if (pgdata_is_empty && tblspaces_are_empty )
351
+ params -> incremental = false;
344
352
345
353
/* no point in checking external directories if their restore is not requested */
346
354
if (!params -> skip_external_dirs )
@@ -602,7 +610,8 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
602
610
* Restore dest_backup internal directories.
603
611
*/
604
612
create_data_directories (dest_files , instance_config .pgdata ,
605
- dest_backup -> root_dir , true, FIO_DB_HOST );
613
+ dest_backup -> root_dir , true,
614
+ params -> incremental , FIO_DB_HOST );
606
615
607
616
/*
608
617
* Restore dest_backup external directories.
@@ -660,16 +669,23 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
660
669
elog (INFO , "Extracting the content of destination directory for incremental restore" );
661
670
662
671
/* TODO: external directorues */
672
+ time (& start_time );
663
673
if (fio_is_remote (FIO_DB_HOST ))
664
674
fio_list_dir (pgdata_files , pgdata_path , false, true, false, false, true, 0 );
665
675
else
666
676
dir_list_file (pgdata_files , pgdata_path ,
667
677
false, true, false, false, true, 0 , FIO_LOCAL_HOST );
668
-
669
678
parray_qsort (pgdata_files , pgFileCompareRelPathWithExternalDesc );
670
- elog (INFO , "Destination directory content extracted, time elapsed:" );
671
679
672
- elog (INFO , "Removing redundant files" );
680
+ time (& end_time );
681
+ pretty_time_interval (difftime (end_time , start_time ),
682
+ pretty_time , lengthof (pretty_time ));
683
+
684
+ elog (INFO , "Destination directory content extracted, time elapsed: %s" ,
685
+ pretty_time );
686
+
687
+ elog (INFO , "Removing redundant files in destination directory" );
688
+ time (& start_time );
673
689
for (i = 0 ; i < parray_num (pgdata_files ); i ++ )
674
690
{
675
691
pgFile * file = (pgFile * ) parray_get (pgdata_files , i );
@@ -686,7 +702,11 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
686
702
}
687
703
}
688
704
689
- elog (INFO , "Redundant files are removed, time elapsed:" );
705
+ time (& end_time );
706
+ pretty_time_interval (difftime (end_time , start_time ),
707
+ pretty_time , lengthof (pretty_time ));
708
+
709
+ elog (INFO , "Redundant files are removed, time elapsed: %s" , pretty_time );
690
710
691
711
// use_bitmap = true;
692
712
/* At this point PDATA do not contain files, that also do not exists in backup filelist */
@@ -756,9 +776,9 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
756
776
elog (INFO , "Backup files are restored. Transfered bytes: %s, time elapsed: %s" ,
757
777
pretty_total_bytes , pretty_time );
758
778
759
- elog (INFO , "Approximate restore efficiency ratio: %.f%% (%s/%s)" ,
760
- ((float ) dest_bytes / total_bytes ) * 100 ,
761
- pretty_dest_bytes , pretty_total_bytes );
779
+ elog (INFO , "Restore overwriting ratio (less is better) : %.f%% (%s/%s)" ,
780
+ ((float ) total_bytes / dest_bytes ) * 100 ,
781
+ pretty_total_bytes , pretty_dest_bytes );
762
782
}
763
783
else
764
784
elog (ERROR , "Backup files restoring failed. Transfered bytes: %s, time elapsed: %s" ,
@@ -921,7 +941,9 @@ restore_files(void *arg)
921
941
922
942
if (arguments -> incremental &&
923
943
parray_bsearch (arguments -> pgdata_files , dest_file , pgFileCompareRelPathWithExternalDesc ))
944
+ {
924
945
already_exists = true;
946
+ }
925
947
926
948
/*
927
949
* Handle incremental restore case for data files.
@@ -933,7 +955,6 @@ restore_files(void *arg)
933
955
dest_file -> is_datafile && !dest_file -> is_cfs &&
934
956
dest_file -> n_blocks > 0 )
935
957
{
936
- elog (INFO , "HELLO" );
937
958
/* remote mode */
938
959
if (fio_is_remote (FIO_DB_HOST ))
939
960
checksum_map = fio_get_checksum_map (to_fullpath , arguments -> dest_backup -> checksum_version ,
@@ -1743,3 +1764,72 @@ get_dbOid_exclude_list(pgBackup *backup, parray *datname_list,
1743
1764
1744
1765
return dbOid_exclude_list ;
1745
1766
}
1767
+
1768
+ /* check that instance has the same SYSTEM_ID, */
1769
+ void
1770
+ check_incremental_compatibility (const char * pgdata , uint64 system_identifier , bool lsn_based )
1771
+ {
1772
+ uint64 system_id_pgdata ;
1773
+ bool success = true;
1774
+ pid_t pid ;
1775
+ char backup_label [MAXPGPATH ];
1776
+
1777
+ /* slurp pg_control and check that system ID is the same */
1778
+ /* check that instance is not running */
1779
+ /* if lsn_based, check that there is no backup_label files is around AND
1780
+ * get redo point lsn from destination pg_control.
1781
+
1782
+ * It is really important to be sure that pg_control is in cohesion with
1783
+ * data files content, because based on pg_control information we will
1784
+ * choose a backup suitable for lsn based incremental restore.
1785
+ */
1786
+ /* TODO: handle timeline discrepancies */
1787
+
1788
+ system_id_pgdata = get_system_identifier (pgdata );
1789
+
1790
+ if (system_id_pgdata != instance_config .system_identifier )
1791
+ {
1792
+ elog (WARNING , "Backup catalog was initialized for system id %lu, "
1793
+ "but destination directory system id is %lu" ,
1794
+ system_identifier , system_id_pgdata );
1795
+ success = false;
1796
+ }
1797
+
1798
+ /* check postmaster pid */
1799
+ if (fio_is_remote (FIO_DB_HOST ))
1800
+ pid = fio_check_postmaster (pgdata );
1801
+ else
1802
+ pid = check_postmaster (pgdata );
1803
+
1804
+ if (pid == 1 ) /* postmaster.pid is mangled */
1805
+ {
1806
+ char pid_file [MAXPGPATH ];
1807
+
1808
+ snprintf (pid_file , MAXPGPATH , "%s/postmaster.pid" , pgdata );
1809
+ elog (WARNING , "Pid file \"%s\" is mangled, cannot determine whether postmaster is running or not" ,
1810
+ pid_file );
1811
+ success = false;
1812
+ }
1813
+ else if (pid > 1 )
1814
+ {
1815
+ elog (WARNING , "Postmaster with pid %u is running in destination directory \"%s\"" ,
1816
+ pid , pgdata );
1817
+ success = false;
1818
+ }
1819
+
1820
+ if (lsn_based )
1821
+ {
1822
+ snprintf (backup_label , MAXPGPATH , "%s/backup_label" , pgdata );
1823
+ if (fio_access (backup_label , F_OK , FIO_DB_HOST ) == 0 )
1824
+ {
1825
+ elog (WARNING , "Destination directory contains \"backup_control\" file. "
1826
+ "It does not mean that you should delete this file, only that "
1827
+ "lsn-based incremental restore is dangerous to use in this case. "
1828
+ "Consider to use checksum-based incremental restore" );
1829
+ success = false;
1830
+ }
1831
+ }
1832
+
1833
+ if (!success )
1834
+ elog (ERROR , "Incremental restore is impossible" );
1835
+ }
0 commit comments