@@ -64,6 +64,8 @@ static int server_version = 0;
64
64
static bool exclusive_backup = false;
65
65
/* Is pg_start_backup() was executed */
66
66
static bool backup_in_progress = false;
67
+ /* Is pg_stop_backup() was sent */
68
+ static bool pg_stop_backup_is_sent = false;
67
69
68
70
typedef struct
69
71
{
@@ -1558,182 +1560,189 @@ pg_stop_backup(pgBackup *backup)
1558
1560
* postgres archive_command problem and in this case we will
1559
1561
* wait for pg_stop_backup() forever.
1560
1562
*/
1561
- if (!exclusive_backup )
1562
- /*
1563
- * Stop the non-exclusive backup. Besides stop_lsn it returns from
1564
- * pg_stop_backup(false) copy of the backup label and tablespace map
1565
- * so they can be written to disk by the caller.
1566
- */
1567
- sent = pgut_send (conn ,
1568
- "SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
1569
- " current_timestamp(0)::timestamptz"
1570
- " FROM pg_stop_backup(false)" ,
1571
- 0 , NULL , WARNING );
1572
- else
1573
- sent = pgut_send (conn ,
1574
- "SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
1575
- " current_timestamp(0)::timestamptz"
1576
- " FROM pg_stop_backup()" ,
1577
- 0 , NULL , WARNING );
1578
-
1579
- if (!sent )
1580
- elog (WARNING , "Failed to send pg_stop_backup query" );
1581
1563
1564
+ if (!pg_stop_backup_is_sent )
1565
+ {
1566
+ if (!exclusive_backup )
1567
+ /*
1568
+ * Stop the non-exclusive backup. Besides stop_lsn it returns from
1569
+ * pg_stop_backup(false) copy of the backup label and tablespace map
1570
+ * so they can be written to disk by the caller.
1571
+ */
1572
+ sent = pgut_send (conn ,
1573
+ "SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
1574
+ " current_timestamp(0)::timestamptz"
1575
+ " FROM pg_stop_backup(false)" ,
1576
+ 0 , NULL , WARNING );
1577
+ else
1578
+ sent = pgut_send (conn ,
1579
+ "SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
1580
+ " current_timestamp(0)::timestamptz"
1581
+ " FROM pg_stop_backup()" ,
1582
+ 0 , NULL , WARNING );
1583
+
1584
+ pg_stop_backup_is_sent = true;
1585
+ if (!sent )
1586
+ elog (ERROR , "Failed to send pg_stop_backup query" );
1587
+ }
1582
1588
1583
1589
/*
1584
1590
* Wait for the result of pg_stop_backup(),
1585
1591
* but no longer than PG_STOP_BACKUP_TIMEOUT seconds
1586
1592
*/
1587
- while ( 1 )
1593
+ if ( pg_stop_backup_is_sent && ! in_cleanup )
1588
1594
{
1589
- if (! PQconsumeInput ( conn ) || PQisBusy ( conn ) )
1595
+ while ( 1 )
1590
1596
{
1591
- pg_stop_backup_timeout ++ ;
1592
- sleep (1 );
1593
-
1594
- if (interrupted )
1597
+ if (!PQconsumeInput (conn ) || PQisBusy (conn ))
1595
1598
{
1596
- pgut_cancel (conn );
1597
- elog (ERROR , "interrupted during waiting for pg_stop_backup" );
1598
- }
1599
+ pg_stop_backup_timeout ++ ;
1600
+ sleep (1 );
1599
1601
1600
- if (pg_stop_backup_timeout == 1 )
1601
- elog (INFO , "wait for pg_stop_backup()" );
1602
+ if (interrupted )
1603
+ {
1604
+ pgut_cancel (conn );
1605
+ elog (ERROR , "interrupted during waiting for pg_stop_backup" );
1606
+ }
1602
1607
1603
- /*
1604
- * If postgres haven't answered in PG_STOP_BACKUP_TIMEOUT seconds,
1605
- * send an interrupt.
1606
- */
1607
- if (pg_stop_backup_timeout > PG_STOP_BACKUP_TIMEOUT )
1608
+ if (pg_stop_backup_timeout == 1 )
1609
+ elog (INFO , "wait for pg_stop_backup()" );
1610
+
1611
+ /*
1612
+ * If postgres haven't answered in PG_STOP_BACKUP_TIMEOUT seconds,
1613
+ * send an interrupt.
1614
+ */
1615
+ if (pg_stop_backup_timeout > PG_STOP_BACKUP_TIMEOUT )
1616
+ {
1617
+ pgut_cancel (conn );
1618
+ elog (ERROR , "pg_stop_backup doesn't answer in %d seconds, cancel it" ,
1619
+ PG_STOP_BACKUP_TIMEOUT );
1620
+ }
1621
+ }
1622
+ else
1608
1623
{
1609
- pgut_cancel (conn );
1610
- elog (ERROR , "pg_stop_backup doesn't answer in %d seconds, cancel it" ,
1611
- PG_STOP_BACKUP_TIMEOUT );
1624
+ res = PQgetResult (conn );
1625
+ break ;
1612
1626
}
1613
1627
}
1614
- else
1615
- {
1616
- res = PQgetResult (conn );
1617
- break ;
1618
- }
1628
+ if (!res )
1629
+ elog (ERROR , "pg_stop backup() failed" );
1619
1630
}
1620
1631
1621
- if (!res )
1622
- elog (ERROR , "pg_stop backup() failed" );
1623
-
1624
1632
backup_in_progress = false;
1625
-
1626
- /* Extract timeline and LSN from results of pg_stop_backup() */
1627
- XLogDataFromLSN (PQgetvalue (res , 0 , 0 ), & xlogid , & xrecoff );
1628
- /* Calculate LSN */
1629
- stop_backup_lsn = (XLogRecPtr ) ((uint64 ) xlogid << 32 ) | xrecoff ;
1630
-
1631
- if (!XRecOffIsValid (stop_backup_lsn ))
1633
+ /* If stop_backup was sent and we are here, it means that is was received */
1634
+ if (pg_stop_backup_is_sent && !in_cleanup )
1632
1635
{
1633
- stop_backup_lsn = restore_lsn ;
1634
- }
1635
-
1636
- if (!XRecOffIsValid (stop_backup_lsn ))
1637
- elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
1638
- (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
1639
-
1640
- /* Write backup_label and tablespace_map for backup from replica */
1641
- if (!exclusive_backup )
1642
- {
1643
- char path [MAXPGPATH ];
1644
- char backup_label [MAXPGPATH ];
1645
- FILE * fp ;
1646
- pgFile * file ;
1647
- size_t len ;
1648
-
1649
- Assert (PQnfields (res ) >= 5 );
1650
-
1651
- pgBackupGetPath (& current , path , lengthof (path ), DATABASE_DIR );
1652
-
1653
- /* Write backup_label */
1654
- join_path_components (backup_label , path , PG_BACKUP_LABEL_FILE );
1655
- fp = fopen (backup_label , "w" );
1656
- if (fp == NULL )
1657
- elog (ERROR , "can't open backup label file \"%s\": %s" ,
1658
- backup_label , strerror (errno ));
1659
-
1660
- len = strlen (PQgetvalue (res , 0 , 1 ));
1661
- if (fwrite (PQgetvalue (res , 0 , 1 ), 1 , len , fp ) != len ||
1662
- fflush (fp ) != 0 ||
1663
- fsync (fileno (fp )) != 0 ||
1664
- fclose (fp ))
1665
- elog (ERROR , "can't write backup label file \"%s\": %s" ,
1666
- backup_label , strerror (errno ));
1636
+ /* Extract timeline and LSN from results of pg_stop_backup() */
1637
+ XLogDataFromLSN (PQgetvalue (res , 0 , 0 ), & xlogid , & xrecoff );
1638
+ /* Calculate LSN */
1639
+ stop_backup_lsn = (XLogRecPtr ) ((uint64 ) xlogid << 32 ) | xrecoff ;
1667
1640
1668
- /*
1669
- * It's vital to check if backup_files_list is initialized,
1670
- * because we could get here because the backup was interrupted
1671
- */
1672
- if (backup_files_list )
1641
+ if (!XRecOffIsValid (stop_backup_lsn ))
1673
1642
{
1674
- file = pgFileNew (backup_label , true);
1675
- calc_file_checksum (file );
1676
- free (file -> path );
1677
- file -> path = strdup (PG_BACKUP_LABEL_FILE );
1678
- parray_append (backup_files_list , file );
1643
+ stop_backup_lsn = restore_lsn ;
1679
1644
}
1680
1645
1681
- /* Write tablespace_map */
1682
- if (strlen (PQgetvalue (res , 0 , 2 )) > 0 )
1646
+ if (!XRecOffIsValid (stop_backup_lsn ))
1647
+ elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
1648
+ (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
1649
+
1650
+ /* Write backup_label and tablespace_map for backup from replica */
1651
+ if (!exclusive_backup )
1683
1652
{
1684
- char tablespace_map [MAXPGPATH ];
1653
+ char path [MAXPGPATH ];
1654
+ char backup_label [MAXPGPATH ];
1655
+ FILE * fp ;
1656
+ pgFile * file ;
1657
+ size_t len ;
1658
+
1659
+ Assert (PQnfields (res ) >= 5 );
1660
+
1661
+ pgBackupGetPath (& current , path , lengthof (path ), DATABASE_DIR );
1685
1662
1686
- join_path_components (tablespace_map , path , PG_TABLESPACE_MAP_FILE );
1687
- fp = fopen (tablespace_map , "w" );
1663
+ /* Write backup_label */
1664
+ join_path_components (backup_label , path , PG_BACKUP_LABEL_FILE );
1665
+ fp = fopen (backup_label , "w" );
1688
1666
if (fp == NULL )
1689
- elog (ERROR , "can't open tablespace map file \"%s\": %s" ,
1690
- tablespace_map , strerror (errno ));
1667
+ elog (ERROR , "can't open backup label file \"%s\": %s" ,
1668
+ backup_label , strerror (errno ));
1691
1669
1692
- len = strlen (PQgetvalue (res , 0 , 2 ));
1693
- if (fwrite (PQgetvalue (res , 0 , 2 ), 1 , len , fp ) != len ||
1670
+ len = strlen (PQgetvalue (res , 0 , 1 ));
1671
+ if (fwrite (PQgetvalue (res , 0 , 1 ), 1 , len , fp ) != len ||
1694
1672
fflush (fp ) != 0 ||
1695
1673
fsync (fileno (fp )) != 0 ||
1696
1674
fclose (fp ))
1697
- elog (ERROR , "can't write tablespace map file \"%s\": %s" ,
1698
- tablespace_map , strerror (errno ));
1675
+ elog (ERROR , "can't write backup label file \"%s\": %s" ,
1676
+ backup_label , strerror (errno ));
1699
1677
1678
+ /*
1679
+ * It's vital to check if backup_files_list is initialized,
1680
+ * because we could get here because the backup was interrupted
1681
+ */
1700
1682
if (backup_files_list )
1701
1683
{
1702
- file = pgFileNew (tablespace_map , true);
1703
- if (S_ISREG (file -> mode ))
1704
- calc_file_checksum (file );
1684
+ file = pgFileNew (backup_label , true);
1685
+ calc_file_checksum (file );
1705
1686
free (file -> path );
1706
- file -> path = strdup (PG_TABLESPACE_MAP_FILE );
1687
+ file -> path = strdup (PG_BACKUP_LABEL_FILE );
1707
1688
parray_append (backup_files_list , file );
1708
1689
}
1709
- }
1710
-
1711
- if (sscanf (PQgetvalue (res , 0 , 3 ), XID_FMT , & recovery_xid ) != 1 )
1712
- elog (ERROR ,
1713
- "result of txid_snapshot_xmax() is invalid: %s" ,
1714
- PQerrorMessage (conn ));
1715
- if (!parse_time (PQgetvalue (res , 0 , 4 ), & recovery_time ))
1716
- elog (ERROR ,
1717
- "result of current_timestamp is invalid: %s" ,
1718
- PQerrorMessage (conn ));
1719
- }
1720
- else
1721
- {
1722
- if (sscanf (PQgetvalue (res , 0 , 1 ), XID_FMT , & recovery_xid ) != 1 )
1723
- elog (ERROR ,
1724
- "result of txid_snapshot_xmax() is invalid: %s" ,
1725
- PQerrorMessage (conn ));
1726
- if (!parse_time (PQgetvalue (res , 0 , 2 ), & recovery_time ))
1727
- elog (ERROR ,
1728
- "result of current_timestamp is invalid: %s" ,
1729
- PQerrorMessage (conn ));
1730
- }
1731
1690
1732
- PQclear (res );
1691
+ /* Write tablespace_map */
1692
+ if (strlen (PQgetvalue (res , 0 , 2 )) > 0 )
1693
+ {
1694
+ char tablespace_map [MAXPGPATH ];
1695
+
1696
+ join_path_components (tablespace_map , path , PG_TABLESPACE_MAP_FILE );
1697
+ fp = fopen (tablespace_map , "w" );
1698
+ if (fp == NULL )
1699
+ elog (ERROR , "can't open tablespace map file \"%s\": %s" ,
1700
+ tablespace_map , strerror (errno ));
1701
+
1702
+ len = strlen (PQgetvalue (res , 0 , 2 ));
1703
+ if (fwrite (PQgetvalue (res , 0 , 2 ), 1 , len , fp ) != len ||
1704
+ fflush (fp ) != 0 ||
1705
+ fsync (fileno (fp )) != 0 ||
1706
+ fclose (fp ))
1707
+ elog (ERROR , "can't write tablespace map file \"%s\": %s" ,
1708
+ tablespace_map , strerror (errno ));
1709
+
1710
+ if (backup_files_list )
1711
+ {
1712
+ file = pgFileNew (tablespace_map , true);
1713
+ if (S_ISREG (file -> mode ))
1714
+ calc_file_checksum (file );
1715
+ free (file -> path );
1716
+ file -> path = strdup (PG_TABLESPACE_MAP_FILE );
1717
+ parray_append (backup_files_list , file );
1718
+ }
1719
+ }
1733
1720
1734
- if (stream_wal )
1735
- /* Wait for the completion of stream */
1736
- pthread_join (stream_thread , NULL );
1721
+ if (sscanf (PQgetvalue (res , 0 , 3 ), XID_FMT , & recovery_xid ) != 1 )
1722
+ elog (ERROR ,
1723
+ "result of txid_snapshot_xmax() is invalid: %s" ,
1724
+ PQerrorMessage (conn ));
1725
+ if (!parse_time (PQgetvalue (res , 0 , 4 ), & recovery_time ))
1726
+ elog (ERROR ,
1727
+ "result of current_timestamp is invalid: %s" ,
1728
+ PQerrorMessage (conn ));
1729
+ }
1730
+ else
1731
+ {
1732
+ if (sscanf (PQgetvalue (res , 0 , 1 ), XID_FMT , & recovery_xid ) != 1 )
1733
+ elog (ERROR ,
1734
+ "result of txid_snapshot_xmax() is invalid: %s" ,
1735
+ PQerrorMessage (conn ));
1736
+ if (!parse_time (PQgetvalue (res , 0 , 2 ), & recovery_time ))
1737
+ elog (ERROR ,
1738
+ "result of current_timestamp is invalid: %s" ,
1739
+ PQerrorMessage (conn ));
1740
+ }
1741
+ PQclear (res );
1742
+ if (stream_wal )
1743
+ /* Wait for the completion of stream */
1744
+ pthread_join (stream_thread , NULL );
1745
+ }
1737
1746
1738
1747
/* Fill in fields if that is the correct end of backup. */
1739
1748
if (backup != NULL )
0 commit comments