@@ -49,6 +49,8 @@ static void pg12_recovery_config(pgBackup *backup, bool add_include);
4949static void restore_chain (pgBackup * dest_backup , parray * parent_chain ,
5050 parray * dbOid_exclude_list , pgRestoreParams * params ,
5151 const char * pgdata_path , bool no_sync );
52+ static void check_incremental_compatibility (const char * pgdata , uint64 system_identifier ,
53+ bool lsn_based );
5254
5355/*
5456 * 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,
111113 char * action = params -> is_restore ? "Restore" :"Validate" ;
112114 parray * parent_chain = NULL ;
113115 parray * dbOid_exclude_list = NULL ;
116+ bool pgdata_is_empty = true;
117+ bool tblspaces_are_empty = true;
114118
115119 if (params -> is_restore )
116120 {
@@ -126,16 +130,17 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
126130 {
127131 elog (INFO , "Running incremental restore into nonempty directory: \"%s\"" ,
128132 instance_config .pgdata );
133+
134+ check_incremental_compatibility (instance_config .pgdata ,
135+ instance_config .system_identifier ,
136+ false);
129137 }
130138 else
131139 elog (ERROR , "Restore destination is not empty: \"%s\"" ,
132140 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;
139144 }
140145 }
141146
@@ -340,7 +345,10 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
340345 */
341346 if (params -> is_restore )
342347 {
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;
344352
345353 /* no point in checking external directories if their restore is not requested */
346354 if (!params -> skip_external_dirs )
@@ -602,7 +610,8 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
602610 * Restore dest_backup internal directories.
603611 */
604612 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 );
606615
607616 /*
608617 * Restore dest_backup external directories.
@@ -660,16 +669,23 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
660669 elog (INFO , "Extracting the content of destination directory for incremental restore" );
661670
662671 /* TODO: external directorues */
672+ time (& start_time );
663673 if (fio_is_remote (FIO_DB_HOST ))
664674 fio_list_dir (pgdata_files , pgdata_path , false, true, false, false, true, 0 );
665675 else
666676 dir_list_file (pgdata_files , pgdata_path ,
667677 false, true, false, false, true, 0 , FIO_LOCAL_HOST );
668-
669678 parray_qsort (pgdata_files , pgFileCompareRelPathWithExternalDesc );
670- elog (INFO , "Destination directory content extracted, time elapsed:" );
671679
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 );
673689 for (i = 0 ; i < parray_num (pgdata_files ); i ++ )
674690 {
675691 pgFile * file = (pgFile * ) parray_get (pgdata_files , i );
@@ -686,7 +702,11 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
686702 }
687703 }
688704
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 );
690710
691711// use_bitmap = true;
692712 /* 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,
756776 elog (INFO , "Backup files are restored. Transfered bytes: %s, time elapsed: %s" ,
757777 pretty_total_bytes , pretty_time );
758778
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 );
762782 }
763783 else
764784 elog (ERROR , "Backup files restoring failed. Transfered bytes: %s, time elapsed: %s" ,
@@ -921,7 +941,9 @@ restore_files(void *arg)
921941
922942 if (arguments -> incremental &&
923943 parray_bsearch (arguments -> pgdata_files , dest_file , pgFileCompareRelPathWithExternalDesc ))
944+ {
924945 already_exists = true;
946+ }
925947
926948 /*
927949 * Handle incremental restore case for data files.
@@ -933,7 +955,6 @@ restore_files(void *arg)
933955 dest_file -> is_datafile && !dest_file -> is_cfs &&
934956 dest_file -> n_blocks > 0 )
935957 {
936- elog (INFO , "HELLO" );
937958 /* remote mode */
938959 if (fio_is_remote (FIO_DB_HOST ))
939960 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,
17431764
17441765 return dbOid_exclude_list ;
17451766}
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