Skip to content

Commit a7bc862

Browse files
committed
PGPRO-1189: for exclusive backups get backup_label and tablespace_map via SQL
1 parent fac4250 commit a7bc862

File tree

3 files changed

+119
-107
lines changed

3 files changed

+119
-107
lines changed

src/backup.c

Lines changed: 107 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
15411525
static void
15421526
pg_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)

src/dir.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static char *pgdata_exclude_files[] =
7575
"recovery.conf",
7676
"postmaster.pid",
7777
"postmaster.opts",
78+
"backup_label",
7879
NULL
7980
};
8081

@@ -398,6 +399,15 @@ dir_list_file_internal(parray *files, const char *root, bool exclude,
398399
file->name = file_name;
399400
}
400401

402+
/* Exclude tablespace_map from backup but we must be aware of it`s existance
403+
* for correct stop_backup procedure in exclusive mode
404+
*/
405+
if (strcmp(file->name, "tablespace_map") == 0)
406+
{
407+
current.tablespace_map_exists = true;
408+
return;
409+
}
410+
401411
/* Check if we need to exclude file by name */
402412
for (i = 0; pgdata_exclude_files[i]; i++)
403413
if (strcmp(file->name, pgdata_exclude_files[i]) == 0)

src/pg_probackup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ typedef struct pgBackup
222222
time_t parent_backup; /* Identifier of the previous backup.
223223
* Which is basic backup for this
224224
* incremental backup. */
225+
/* Is tablespace_map exists in PGDATA */
226+
bool tablespace_map_exists;
225227
} pgBackup;
226228

227229
/* Recovery target for restore and validate subcommands */

0 commit comments

Comments
 (0)