@@ -475,6 +475,8 @@ do_backup_instance(void)
475475 pgBackup * prev_backup = NULL ;
476476 parray * prev_backup_filelist = NULL ;
477477
478+ pgFile * pg_control = NULL ;
479+
478480 elog (LOG , "Database backup start" );
479481
480482 /* Initialize size summary */
@@ -754,9 +756,34 @@ do_backup_instance(void)
754756 parray_free (prev_backup_filelist );
755757 }
756758
759+ /* In case of backup from replica >= 9.6 we must fix minRecPoint,
760+ * First we must find pg_control in backup_files_list.
761+ */
762+ if (current .from_replica && !exclusive_backup )
763+ {
764+ char pg_control_path [MAXPGPATH ];
765+
766+ snprintf (pg_control_path , sizeof (pg_control_path ), "%s/%s" , pgdata , "global/pg_control" );
767+
768+ for (i = 0 ; i < parray_num (backup_files_list ); i ++ )
769+ {
770+ pgFile * tmp_file = (pgFile * ) parray_get (backup_files_list , i );
771+
772+ if (strcmp (tmp_file -> path , pg_control_path ) == 0 )
773+ {
774+ pg_control = tmp_file ;
775+ break ;
776+ }
777+ }
778+ }
779+
780+
757781 /* Notify end of backup */
758782 pg_stop_backup (& current );
759783
784+ if (current .from_replica && !exclusive_backup )
785+ set_min_recovery_point (pg_control , database_path , current .stop_lsn );
786+
760787 /* Add archived xlog files into the list of files of this backup */
761788 if (stream_wal )
762789 {
@@ -883,7 +910,7 @@ do_backup(time_t start_time)
883910 }
884911 }
885912
886- if (current .from_replica )
913+ if (current .from_replica && exclusive_backup )
887914 {
888915 /* Check master connection options */
889916 if (master_host == NULL )
@@ -1089,8 +1116,11 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
10891116
10901117 params [0 ] = label ;
10911118
1092- /* For replica we call pg_start_backup() on master */
1093- conn = (backup -> from_replica ) ? master_conn : backup_conn ;
1119+ /* For 9.5 replica we call pg_start_backup() on master */
1120+ if (backup -> from_replica && exclusive_backup )
1121+ conn = master_conn ;
1122+ else
1123+ conn = backup_conn ;
10941124
10951125 /* 2nd argument is 'fast'*/
10961126 params [1 ] = smooth ? "false" : "true" ;
@@ -1118,16 +1148,18 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
11181148
11191149 PQclear (res );
11201150
1121- if (current .backup_mode == BACKUP_MODE_DIFF_PAGE )
1151+ if (current .backup_mode == BACKUP_MODE_DIFF_PAGE &&
1152+ (!(backup -> from_replica && !exclusive_backup )))
11221153 /*
11231154 * Switch to a new WAL segment. It is necessary to get archived WAL
11241155 * segment, which includes start LSN of current backup.
1156+ * Don`t do this for replica backups unless it`s PG 9.5
11251157 */
11261158 pg_switch_wal (conn );
11271159
11281160 if (current .backup_mode == BACKUP_MODE_DIFF_PAGE )
11291161 /* In PAGE mode wait for current segment... */
1130- wait_wal_lsn (backup -> start_lsn , true, false);
1162+ wait_wal_lsn (backup -> start_lsn , true, false);
11311163 /*
11321164 * Do not wait start_lsn for stream backup.
11331165 * Because WAL streaming will start after pg_start_backup() in stream
@@ -1137,8 +1169,10 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
11371169 /* ...for others wait for previous segment */
11381170 wait_wal_lsn (backup -> start_lsn , true, true);
11391171
1140- /* Wait for start_lsn to be replayed by replica */
1141- if (backup -> from_replica )
1172+ /* In case of backup from replica for PostgreSQL 9.5
1173+ * wait for start_lsn to be replayed by replica
1174+ */
1175+ if (backup -> from_replica && exclusive_backup )
11421176 wait_replica_wal_lsn (backup -> start_lsn , true);
11431177}
11441178
@@ -1488,7 +1522,7 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
14881522 GetXLogFileName (wal_segment , tli , targetSegNo , xlog_seg_size );
14891523
14901524 /*
1491- * In pg_start_backup we wait for 'lsn' in 'pg_wal' directory iff it is
1525+ * In pg_start_backup we wait for 'lsn' in 'pg_wal' directory if it is
14921526 * stream and non-page backup. Page backup needs archived WAL files, so we
14931527 * wait for 'lsn' in archive 'wal' directory for page backups.
14941528 *
@@ -1509,7 +1543,12 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
15091543 {
15101544 join_path_components (wal_segment_path , arclog_path , wal_segment );
15111545 wal_segment_dir = arclog_path ;
1512- timeout = archive_timeout ;
1546+
1547+ if (archive_timeout > 0 )
1548+ timeout = archive_timeout ;
1549+ else
1550+ timeout = ARCHIVE_TIMEOUT_DEFAULT ;
1551+
15131552 }
15141553
15151554 if (wait_prev_segment )
@@ -1669,7 +1708,7 @@ pg_stop_backup(pgBackup *backup)
16691708 PGresult * tablespace_map_content = NULL ;
16701709 uint32 lsn_hi ;
16711710 uint32 lsn_lo ;
1672- XLogRecPtr restore_lsn = InvalidXLogRecPtr ;
1711+ // XLogRecPtr restore_lsn = InvalidXLogRecPtr;
16731712 int pg_stop_backup_timeout = 0 ;
16741713 char path [MAXPGPATH ];
16751714 char backup_label [MAXPGPATH ];
@@ -1689,16 +1728,21 @@ pg_stop_backup(pgBackup *backup)
16891728 if (!backup_in_progress )
16901729 elog (ERROR , "backup is not in progress" );
16911730
1692- /* For replica we call pg_stop_backup() on master */
1693- conn = (current .from_replica ) ? master_conn : backup_conn ;
1731+ /* For 9.5 replica we call pg_stop_backup() on master */
1732+ if (current .from_replica && exclusive_backup )
1733+ conn = master_conn ;
1734+ else
1735+ conn = backup_conn ;
16941736
16951737 /* Remove annoying NOTICE messages generated by backend */
16961738 res = pgut_execute (conn , "SET client_min_messages = warning;" ,
16971739 0 , NULL );
16981740 PQclear (res );
16991741
1700- /* Create restore point */
1701- if (backup != NULL )
1742+ /* Create restore point
1743+ * only if it`s backup from master, or exclusive replica(wich connects to master)
1744+ */
1745+ if (backup != NULL && (!current .from_replica || (current .from_replica && exclusive_backup )))
17021746 {
17031747 const char * params [1 ];
17041748 char name [1024 ];
@@ -1716,7 +1760,7 @@ pg_stop_backup(pgBackup *backup)
17161760 /* Extract timeline and LSN from the result */
17171761 XLogDataFromLSN (PQgetvalue (res , 0 , 0 ), & lsn_hi , & lsn_lo );
17181762 /* Calculate LSN */
1719- restore_lsn = ((uint64 ) lsn_hi ) << 32 | lsn_lo ;
1763+ // restore_lsn = ((uint64) lsn_hi) << 32 | lsn_lo;
17201764 PQclear (res );
17211765 }
17221766
@@ -1737,14 +1781,29 @@ pg_stop_backup(pgBackup *backup)
17371781 * Stop the non-exclusive backup. Besides stop_lsn it returns from
17381782 * pg_stop_backup(false) copy of the backup label and tablespace map
17391783 * so they can be written to disk by the caller.
1784+ * In case of backup from replica >= 9.6 we do not trust minRecPoint
1785+ * and stop_backup LSN, so we use latest replayed LSN as STOP LSN.
17401786 */
1741- stop_backup_query = "SELECT"
1742- " pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1743- " current_timestamp(0)::timestamptz,"
1744- " lsn,"
1745- " labelfile,"
1746- " spcmapfile"
1747- " FROM pg_catalog.pg_stop_backup(false)" ;
1787+ if (current .from_replica )
1788+ stop_backup_query = "SELECT"
1789+ " pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1790+ " current_timestamp(0)::timestamptz,"
1791+ #if PG_VERSION_NUM >= 100000
1792+ " pg_catalog.pg_last_wal_replay_lsn(),"
1793+ #else
1794+ " pg_catalog.pg_last_xlog_replay_location(),"
1795+ #endif
1796+ " labelfile,"
1797+ " spcmapfile"
1798+ " FROM pg_catalog.pg_stop_backup(false)" ;
1799+ else
1800+ stop_backup_query = "SELECT"
1801+ " pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1802+ " current_timestamp(0)::timestamptz,"
1803+ " lsn,"
1804+ " labelfile,"
1805+ " spcmapfile"
1806+ " FROM pg_catalog.pg_stop_backup(false)" ;
17481807
17491808 }
17501809 else
@@ -1832,13 +1891,13 @@ pg_stop_backup(pgBackup *backup)
18321891
18331892 if (!XRecOffIsValid (stop_backup_lsn ))
18341893 {
1835- stop_backup_lsn = restore_lsn ;
1894+ if (XRecOffIsNull (stop_backup_lsn ))
1895+ stop_backup_lsn = stop_backup_lsn + SizeOfXLogLongPHD ;
1896+ else
1897+ elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
1898+ (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
18361899 }
18371900
1838- if (!XRecOffIsValid (stop_backup_lsn ))
1839- elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
1840- (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
1841-
18421901 /* Write backup_label and tablespace_map */
18431902 if (!exclusive_backup )
18441903 {
@@ -1939,7 +1998,7 @@ pg_stop_backup(pgBackup *backup)
19391998 stream_xlog_path [MAXPGPATH ];
19401999
19412000 /* Wait for stop_lsn to be received by replica */
1942- if (backup -> from_replica )
2001+ if (current . from_replica )
19432002 wait_replica_wal_lsn (stop_backup_lsn , false);
19442003 /*
19452004 * Wait for stop_lsn to be archived or streamed.
@@ -1962,10 +2021,12 @@ pg_stop_backup(pgBackup *backup)
19622021
19632022 elog (LOG , "Getting the Recovery Time from WAL" );
19642023
2024+ /* iterate over WAL from stop_backup lsn to start_backup lsn */
19652025 if (!read_recovery_info (xlog_path , backup -> tli , xlog_seg_size ,
19662026 backup -> start_lsn , backup -> stop_lsn ,
19672027 & backup -> recovery_time , & backup -> recovery_xid ))
19682028 {
2029+ elog (LOG , "Failed to find Recovery Time in WAL. Forced to trust current_timestamp" );
19692030 backup -> recovery_time = recovery_time ;
19702031 backup -> recovery_xid = recovery_xid ;
19712032 }
@@ -2074,7 +2135,7 @@ backup_files(void *arg)
20742135 elog (ERROR , "interrupted during backup" );
20752136
20762137 if (progress )
2077- elog (LOG , "Progress: (%d/%d). Process file \"%s\"" ,
2138+ elog (INFO , "Progress: (%d/%d). Process file \"%s\"" ,
20782139 i + 1 , n_backup_files_list , file -> path );
20792140
20802141 /* stat file to check its current state */
@@ -2168,7 +2229,7 @@ backup_files(void *arg)
21682229 file -> path , file -> write_size );
21692230 }
21702231 else
2171- elog (LOG , "unexpected file type %d" , buf .st_mode );
2232+ elog (WARNING , "unexpected file type %d" , buf .st_mode );
21722233 }
21732234
21742235 /* Close connection */
0 commit comments