@@ -109,7 +109,7 @@ static int checkpoint_timeout(void);
109109//static void backup_list_file(parray *files, const char *root, )
110110static void parse_backup_filelist_filenames (parray * files , const char * root );
111111static void wait_wal_lsn (XLogRecPtr lsn , bool is_start_lsn ,
112- bool wait_prev_segment );
112+ bool wait_prev_lsn , bool wait_prev_segment );
113113static void wait_replica_wal_lsn (XLogRecPtr lsn , bool is_start_backup );
114114static void make_pagemap_from_ptrack (parray * files );
115115static void * StreamLog (void * arg );
@@ -1166,15 +1166,15 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
11661166
11671167 if (current .backup_mode == BACKUP_MODE_DIFF_PAGE )
11681168 /* In PAGE mode wait for current segment... */
1169- wait_wal_lsn (backup -> start_lsn , true, false);
1169+ wait_wal_lsn (backup -> start_lsn , true, false , false);
11701170 /*
11711171 * Do not wait start_lsn for stream backup.
11721172 * Because WAL streaming will start after pg_start_backup() in stream
11731173 * mode.
11741174 */
11751175 else if (!stream_wal )
11761176 /* ...for others wait for previous segment */
1177- wait_wal_lsn (backup -> start_lsn , true, true);
1177+ wait_wal_lsn (backup -> start_lsn , true, false, true);
11781178
11791179 /* In case of backup from replica for PostgreSQL 9.5
11801180 * wait for start_lsn to be replayed by replica
@@ -1504,7 +1504,8 @@ pg_ptrack_get_and_clear(Oid tablespace_oid, Oid db_oid, Oid rel_filenode,
15041504 * If 'wait_prev_segment' wait for previous segment.
15051505 */
15061506static void
1507- wait_wal_lsn (XLogRecPtr lsn , bool is_start_lsn , bool wait_prev_segment )
1507+ wait_wal_lsn (XLogRecPtr lsn , bool is_start_lsn , bool wait_prev_lsn ,
1508+ bool wait_prev_segment )
15081509{
15091510 TimeLineID tli ;
15101511 XLogSegNo targetSegNo ;
@@ -1515,6 +1516,7 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
15151516 bool file_exists = false;
15161517 uint32 try_count = 0 ,
15171518 timeout ;
1519+ char * prior_to = (wait_prev_lsn ) ? " prior to " : "" ;
15181520
15191521#ifdef HAVE_LIBZ
15201522 char gz_wal_segment_path [MAXPGPATH ];
@@ -1555,14 +1557,13 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
15551557 timeout = archive_timeout ;
15561558 else
15571559 timeout = ARCHIVE_TIMEOUT_DEFAULT ;
1558-
15591560 }
15601561
15611562 if (wait_prev_segment )
15621563 elog (LOG , "Looking for segment: %s" , wal_segment );
15631564 else
1564- elog (LOG , "Looking for LSN: %X/%X in segment: %s" ,
1565- (uint32 ) (lsn >> 32 ), (uint32 ) lsn , wal_segment );
1565+ elog (LOG , "Looking for LSN %s %X/%X in segment: %s" ,
1566+ prior_to , (uint32 ) (lsn >> 32 ), (uint32 ) lsn , wal_segment );
15661567
15671568#ifdef HAVE_LIBZ
15681569 snprintf (gz_wal_segment_path , sizeof (gz_wal_segment_path ), "%s.gz" ,
@@ -1598,11 +1599,27 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
15981599 /*
15991600 * A WAL segment found. Check LSN on it.
16001601 */
1601- if (wal_contains_lsn (wal_segment_dir , lsn , tli , xlog_seg_size ))
1602- /* Target LSN was found */
1602+ if (!wait_prev_lsn )
16031603 {
1604- elog (LOG , "Found LSN: %X/%X" , (uint32 ) (lsn >> 32 ), (uint32 ) lsn );
1605- return ;
1604+ if (wal_contains_lsn (wal_segment_dir , lsn , tli , xlog_seg_size ))
1605+ /* Target LSN was found */
1606+ {
1607+ elog (LOG , "Found LSN: %X/%X" , (uint32 ) (lsn >> 32 ), (uint32 ) lsn );
1608+ return ;
1609+ }
1610+ }
1611+ else
1612+ {
1613+ XLogRecPtr res ;
1614+
1615+ res = get_last_wal_lsn (wal_segment_dir , current .start_lsn ,
1616+ lsn , tli , false, xlog_seg_size );
1617+ if (!XLogRecPtrIsInvalid (res ))
1618+ {
1619+ /* LSN of the prior record was found */
1620+ elog (LOG , "Found LSN: %X/%X" , (uint32 ) (res >> 32 ), (uint32 ) res );
1621+ return ;
1622+ }
16061623 }
16071624 }
16081625
@@ -1618,16 +1635,18 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
16181635 elog (INFO , "Wait for WAL segment %s to be archived" ,
16191636 wal_segment_path );
16201637 else
1621- elog (INFO , "Wait for LSN %X/%X in archived WAL segment %s" ,
1622- (uint32 ) (lsn >> 32 ), (uint32 ) lsn , wal_segment_path );
1638+ elog (INFO , "Wait for LSN %s%X/%X in archived WAL segment %s" ,
1639+ prior_to , (uint32 ) (lsn >> 32 ), (uint32 ) lsn ,
1640+ wal_segment_path );
16231641 }
16241642
16251643 if (timeout > 0 && try_count > timeout )
16261644 {
16271645 if (file_exists )
16281646 elog (ERROR , "WAL segment %s was archived, "
1629- "but target LSN %X/%X could not be archived in %d seconds" ,
1630- wal_segment , (uint32 ) (lsn >> 32 ), (uint32 ) lsn , timeout );
1647+ "but target LSN %s%X/%X could not be archived in %d seconds" ,
1648+ wal_segment , prior_to , (uint32 ) (lsn >> 32 ), (uint32 ) lsn ,
1649+ timeout );
16311650 /* If WAL segment doesn't exist or we wait for previous segment */
16321651 else
16331652 elog (ERROR ,
@@ -1724,6 +1743,7 @@ pg_stop_backup(pgBackup *backup)
17241743 size_t len ;
17251744 char * val = NULL ;
17261745 char * stop_backup_query = NULL ;
1746+ bool stop_lsn_exists = false;
17271747
17281748 /*
17291749 * We will use this values if there are no transactions between start_lsn
@@ -1910,7 +1930,6 @@ pg_stop_backup(pgBackup *backup)
19101930 {
19111931 char * xlog_path ,
19121932 stream_xlog_path [MAXPGPATH ];
1913- XLogSegNo segno ;
19141933
19151934 if (stream_wal )
19161935 {
@@ -1922,12 +1941,14 @@ pg_stop_backup(pgBackup *backup)
19221941 else
19231942 xlog_path = arclog_path ;
19241943
1925- GetXLogSegNo (stop_backup_lsn , segno , xlog_seg_size );
1926- /* Retreive stop_lsn from previous segment */
1927- segno = segno - 1 ;
19281944 stop_backup_lsn = get_last_wal_lsn (xlog_path , backup -> start_lsn ,
1929- segno , backup -> tli ,
1930- xlog_seg_size );
1945+ stop_backup_lsn , backup -> tli ,
1946+ true, xlog_seg_size );
1947+ /*
1948+ * Do not check existance of LSN again below using
1949+ * wait_wal_lsn().
1950+ */
1951+ stop_lsn_exists = true;
19311952 }
19321953 else
19331954 elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
@@ -2040,7 +2061,9 @@ pg_stop_backup(pgBackup *backup)
20402061 * Wait for stop_lsn to be archived or streamed.
20412062 * We wait for stop_lsn in stream mode just in case.
20422063 */
2043- wait_wal_lsn (stop_backup_lsn , false, false);
2064+ if (!stop_lsn_exists )
2065+ wait_wal_lsn (stop_backup_lsn , false,
2066+ !exclusive_backup && current .from_replica , false);
20442067
20452068 if (stream_wal )
20462069 {
0 commit comments