@@ -457,6 +457,8 @@ do_backup_instance(void)
457457 /* Initialize size summary */
458458 current .data_bytes = 0 ;
459459
460+ current .tablespace_map_exists = false;
461+
460462 /* Obtain current timeline */
461463 if (is_remote_backup )
462464 {
@@ -520,24 +522,6 @@ do_backup_instance(void)
520522 strncat (label , " with pg_probackup" , lengthof (label ));
521523 pg_start_backup (label , smooth_checkpoint , & current );
522524
523- /*
524- * If backup_label does not exist in $PGDATA, stop taking backup.
525- * NOTE. We can check it only on master, though.
526- */
527- if (exclusive_backup )
528- {
529- char label_path [MAXPGPATH ];
530- join_path_components (label_path , pgdata , PG_BACKUP_LABEL_FILE );
531-
532- /* Leave if no backup file */
533- if (!fileExists (label_path ))
534- {
535- elog (LOG , "%s does not exist, stopping backup" , PG_BACKUP_LABEL_FILE );
536- pg_stop_backup (NULL );
537- elog (ERROR , "%s does not exist in PGDATA" , PG_BACKUP_LABEL_FILE );
538- }
539- }
540-
541525 pgBackupGetPath (& current , database_path , lengthof (database_path ),
542526 DATABASE_DIR );
543527
@@ -1541,13 +1525,20 @@ wait_replica_wal_lsn(XLogRecPtr lsn, bool is_start_backup)
15411525static void
15421526pg_stop_backup (pgBackup * backup )
15431527{
1544- PGconn * conn ;
1545- PGresult * res ;
1528+ PGconn * conn ;
1529+ PGresult * res ;
1530+ PGresult * tablespace_map_content = NULL ;
15461531 uint32 xlogid ;
15471532 uint32 xrecoff ;
15481533 XLogRecPtr restore_lsn = InvalidXLogRecPtr ;
1549- bool sent = false;
1550- int pg_stop_backup_timeout = 0 ;
1534+ bool sent = false;
1535+ int pg_stop_backup_timeout = 0 ;
1536+ char path [MAXPGPATH ];
1537+ char backup_label [MAXPGPATH ];
1538+ FILE * fp ;
1539+ pgFile * file ;
1540+ size_t len ;
1541+ char * val = NULL ;
15511542
15521543 /*
15531544 * We will use this values if there are no transactions between start_lsn
@@ -1601,23 +1592,39 @@ pg_stop_backup(pgBackup *backup)
16011592 if (!pg_stop_backup_is_sent )
16021593 {
16031594 if (!exclusive_backup )
1595+ {
16041596 /*
16051597 * Stop the non-exclusive backup. Besides stop_lsn it returns from
16061598 * pg_stop_backup(false) copy of the backup label and tablespace map
16071599 * so they can be written to disk by the caller.
16081600 */
16091601 sent = pgut_send (conn ,
1610- "SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
1611- " current_timestamp(0)::timestamptz"
1612- " FROM pg_stop_backup(false)" ,
1613- 0 , NULL , WARNING );
1602+ "SELECT"
1603+ " labelfile,"
1604+ " txid_snapshot_xmax(txid_current_snapshot()),"
1605+ " current_timestamp(0)::timestamptz,"
1606+ " lsn,"
1607+ " spcmapfile"
1608+ " FROM pg_stop_backup(false)" ,
1609+ 0 , NULL , WARNING );
1610+ }
16141611 else
1612+ {
1613+ if (current .tablespace_map_exists )
1614+ {
1615+ /* We cannot execute pg_read_file after pg_stop_backup */
1616+ tablespace_map_content = pgut_execute (conn ,
1617+ "SELECT pg_read_file('tablespace_map')" ,
1618+ 0 , NULL );
1619+ }
16151620 sent = pgut_send (conn ,
1616- "SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
1617- " current_timestamp(0)::timestamptz"
1618- " FROM pg_stop_backup()" ,
1619- 0 , NULL , WARNING );
1620-
1621+ "SELECT"
1622+ " pg_read_file('backup_label') as labelfile,"
1623+ " txid_snapshot_xmax(txid_current_snapshot()),"
1624+ " current_timestamp(0)::timestamptz,"
1625+ " pg_stop_backup() as lsn" ,
1626+ 0 , NULL , WARNING );
1627+ }
16211628 pg_stop_backup_is_sent = true;
16221629 if (!sent )
16231630 elog (ERROR , "Failed to send pg_stop_backup query" );
@@ -1673,7 +1680,7 @@ pg_stop_backup(pgBackup *backup)
16731680 if (pg_stop_backup_is_sent && !in_cleanup )
16741681 {
16751682 /* Extract timeline and LSN from results of pg_stop_backup() */
1676- XLogDataFromLSN (PQgetvalue (res , 0 , 0 ), & xlogid , & xrecoff );
1683+ XLogDataFromLSN (PQgetvalue (res , 0 , 3 ), & xlogid , & xrecoff );
16771684 /* Calculate LSN */
16781685 stop_backup_lsn = (XLogRecPtr ) ((uint64 ) xlogid << 32 ) | xrecoff ;
16791686
@@ -1686,96 +1693,89 @@ pg_stop_backup(pgBackup *backup)
16861693 elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
16871694 (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
16881695
1689- /* Write backup_label and tablespace_map for backup from replica */
1690- if (!exclusive_backup )
1696+ /* Write backup_label and tablespace_map */
1697+ Assert (PQnfields (res ) >= 4 );
1698+ pgBackupGetPath (& current , path , lengthof (path ), DATABASE_DIR );
1699+
1700+ /* Write backup_label */
1701+ join_path_components (backup_label , path , PG_BACKUP_LABEL_FILE );
1702+ fp = fopen (backup_label , "w" );
1703+ if (fp == NULL )
1704+ elog (ERROR , "can't open backup label file \"%s\": %s" ,
1705+ backup_label , strerror (errno ));
1706+
1707+ len = strlen (PQgetvalue (res , 0 , 0 ));
1708+ if (fwrite (PQgetvalue (res , 0 , 0 ), 1 , len , fp ) != len ||
1709+ fflush (fp ) != 0 ||
1710+ fsync (fileno (fp )) != 0 ||
1711+ fclose (fp ))
1712+ elog (ERROR , "can't write backup label file \"%s\": %s" ,
1713+ backup_label , strerror (errno ));
1714+
1715+ /*
1716+ * It's vital to check if backup_files_list is initialized,
1717+ * because we could get here because the backup was interrupted
1718+ */
1719+ if (backup_files_list )
16911720 {
1692- char path [MAXPGPATH ];
1693- char backup_label [MAXPGPATH ];
1694- FILE * fp ;
1695- pgFile * file ;
1696- size_t len ;
1721+ file = pgFileNew (backup_label , true);
1722+ calc_file_checksum (file );
1723+ free (file -> path );
1724+ file -> path = strdup (PG_BACKUP_LABEL_FILE );
1725+ parray_append (backup_files_list , file );
1726+ }
16971727
1698- Assert (PQnfields (res ) >= 5 );
1728+ if (sscanf (PQgetvalue (res , 0 , 1 ), XID_FMT , & recovery_xid ) != 1 )
1729+ elog (ERROR ,
1730+ "result of txid_snapshot_xmax() is invalid: %s" ,
1731+ PQerrorMessage (conn ));
1732+ if (!parse_time (PQgetvalue (res , 0 , 2 ), & recovery_time ))
1733+ elog (ERROR ,
1734+ "result of current_timestamp is invalid: %s" ,
1735+ PQerrorMessage (conn ));
1736+
1737+ /* Get content for tablespace_map from pg_read_file('tablespace_map') in case of exclusive
1738+ * or from stop_backup results in case of non-exclusive backup
1739+ */
1740+ if (exclusive_backup )
1741+ {
1742+ if (current .tablespace_map_exists )
1743+ {
1744+ val = PQgetvalue (tablespace_map_content , 0 , 0 );
1745+ PQclear (tablespace_map_content );
1746+ }
1747+ }
1748+ else
1749+ val = PQgetvalue (res , 0 , 4 );
16991750
1700- pgBackupGetPath (& current , path , lengthof (path ), DATABASE_DIR );
1751+ /* Write tablespace_map */
1752+ if (val && strlen (val ) > 0 )
1753+ {
1754+ char tablespace_map [MAXPGPATH ];
17011755
1702- /* Write backup_label */
1703- join_path_components (backup_label , path , PG_BACKUP_LABEL_FILE );
1704- fp = fopen (backup_label , "w" );
1756+ join_path_components (tablespace_map , path , PG_TABLESPACE_MAP_FILE );
1757+ fp = fopen (tablespace_map , "w" );
17051758 if (fp == NULL )
1706- elog (ERROR , "can't open backup label file \"%s\": %s" ,
1707- backup_label , strerror (errno ));
1759+ elog (ERROR , "can't open tablespace map file \"%s\": %s" ,
1760+ tablespace_map , strerror (errno ));
17081761
1709- len = strlen (PQgetvalue ( res , 0 , 1 ) );
1710- if (fwrite (PQgetvalue ( res , 0 , 1 ) , 1 , len , fp ) != len ||
1762+ len = strlen (val );
1763+ if (fwrite (val , 1 , len , fp ) != len ||
17111764 fflush (fp ) != 0 ||
17121765 fsync (fileno (fp )) != 0 ||
17131766 fclose (fp ))
1714- elog (ERROR , "can't write backup label file \"%s\": %s" ,
1715- backup_label , strerror (errno ));
1767+ elog (ERROR , "can't write tablespace map file \"%s\": %s" ,
1768+ tablespace_map , strerror (errno ));
17161769
1717- /*
1718- * It's vital to check if backup_files_list is initialized,
1719- * because we could get here because the backup was interrupted
1720- */
17211770 if (backup_files_list )
17221771 {
1723- file = pgFileNew (backup_label , true);
1724- calc_file_checksum (file );
1772+ file = pgFileNew (tablespace_map , true);
1773+ if (S_ISREG (file -> mode ))
1774+ calc_file_checksum (file );
17251775 free (file -> path );
1726- file -> path = strdup (PG_BACKUP_LABEL_FILE );
1776+ file -> path = strdup (PG_TABLESPACE_MAP_FILE );
17271777 parray_append (backup_files_list , file );
17281778 }
1729-
1730- /* Write tablespace_map */
1731- if (strlen (PQgetvalue (res , 0 , 2 )) > 0 )
1732- {
1733- char tablespace_map [MAXPGPATH ];
1734-
1735- join_path_components (tablespace_map , path , PG_TABLESPACE_MAP_FILE );
1736- fp = fopen (tablespace_map , "w" );
1737- if (fp == NULL )
1738- elog (ERROR , "can't open tablespace map file \"%s\": %s" ,
1739- tablespace_map , strerror (errno ));
1740-
1741- len = strlen (PQgetvalue (res , 0 , 2 ));
1742- if (fwrite (PQgetvalue (res , 0 , 2 ), 1 , len , fp ) != len ||
1743- fflush (fp ) != 0 ||
1744- fsync (fileno (fp )) != 0 ||
1745- fclose (fp ))
1746- elog (ERROR , "can't write tablespace map file \"%s\": %s" ,
1747- tablespace_map , strerror (errno ));
1748-
1749- if (backup_files_list )
1750- {
1751- file = pgFileNew (tablespace_map , true);
1752- if (S_ISREG (file -> mode ))
1753- calc_file_checksum (file );
1754- free (file -> path );
1755- file -> path = strdup (PG_TABLESPACE_MAP_FILE );
1756- parray_append (backup_files_list , file );
1757- }
1758- }
1759-
1760- if (sscanf (PQgetvalue (res , 0 , 3 ), XID_FMT , & recovery_xid ) != 1 )
1761- elog (ERROR ,
1762- "result of txid_snapshot_xmax() is invalid: %s" ,
1763- PQerrorMessage (conn ));
1764- if (!parse_time (PQgetvalue (res , 0 , 4 ), & recovery_time ))
1765- elog (ERROR ,
1766- "result of current_timestamp is invalid: %s" ,
1767- PQerrorMessage (conn ));
1768- }
1769- else
1770- {
1771- if (sscanf (PQgetvalue (res , 0 , 1 ), XID_FMT , & recovery_xid ) != 1 )
1772- elog (ERROR ,
1773- "result of txid_snapshot_xmax() is invalid: %s" ,
1774- PQerrorMessage (conn ));
1775- if (!parse_time (PQgetvalue (res , 0 , 2 ), & recovery_time ))
1776- elog (ERROR ,
1777- "result of current_timestamp is invalid: %s" ,
1778- PQerrorMessage (conn ));
17791779 }
17801780 PQclear (res );
17811781 if (stream_wal )
0 commit comments