Skip to content

Commit e2bbf69

Browse files
author
Michael Paquier
committed
Remove code duplication to get a node's current timeline
The same code was duplicated between restore and backup. At the same time this commit introduces routines to fetch the control data file.
1 parent a5a76c1 commit e2bbf69

File tree

4 files changed

+61
-83
lines changed

4 files changed

+61
-83
lines changed

backup.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <dirent.h>
1818
#include <time.h>
1919

20-
#include "catalog/pg_control.h"
2120
#include "libpq/pqsignal.h"
2221
#include "pgut/pgut-port.h"
2322

@@ -54,7 +53,6 @@ static void create_file_list(parray *files,
5453
const char *subdir,
5554
const char *prefix,
5655
bool is_append);
57-
static TimeLineID get_current_timeline(void);
5856

5957
/*
6058
* Take a backup of database and return the list of files backed up.
@@ -1047,27 +1045,3 @@ create_file_list(parray *files,
10471045
fclose(fp);
10481046
}
10491047
}
1050-
1051-
/*
1052-
* Scan control file of given cluster at obtain the current timeline
1053-
* since last checkpoint that occurred on it.
1054-
*/
1055-
static TimeLineID
1056-
get_current_timeline(void)
1057-
{
1058-
char *buffer;
1059-
size_t size;
1060-
ControlFileData control_file;
1061-
1062-
/* First fetch file... */
1063-
buffer = slurpFile(pgdata, "global/pg_control", &size);
1064-
1065-
/* .. Then interpret it */
1066-
if (size != PG_CONTROL_SIZE)
1067-
elog(ERROR_CORRUPTED, "unexpected control file size %d, expected %d",
1068-
(int) size, PG_CONTROL_SIZE);
1069-
memcpy(&control_file, buffer, sizeof(ControlFileData));
1070-
1071-
/* Finally return the timeline wanted */
1072-
return control_file.checkPointCopy.ThisTimeLineID;
1073-
}

pg_arman.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ extern bool copy_file(const char *from_root, const char *to_root,
289289
pgFile *file);
290290

291291
/* in util.c */
292+
extern TimeLineID get_current_timeline(void);
292293
extern void time2iso(char *buf, size_t len, time_t time);
293294
extern const char *status2str(BackupStatus status);
294295
extern void remove_trailing_space(char *buf, int comment_mark);

restore.c

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ static parray * readTimeLineHistory(TimeLineID targetTLI);
2929
static bool satisfy_timeline(const parray *timelines, const pgBackup *backup);
3030
static bool satisfy_recovery_target(const pgBackup *backup,
3131
const pgRecoveryTarget *rt);
32-
static TimeLineID get_current_timeline(void);
3332
static TimeLineID get_fullbackup_timeline(parray *backups,
3433
const pgRecoveryTarget *rt);
3534
static void print_backup_lsn(const pgBackup *backup);
@@ -624,62 +623,6 @@ satisfy_timeline(const parray *timelines, const pgBackup *backup)
624623
return false;
625624
}
626625

627-
/* get TLI of the current database */
628-
static TimeLineID
629-
get_current_timeline(void)
630-
{
631-
ControlFileData ControlFile;
632-
int fd;
633-
char ControlFilePath[MAXPGPATH];
634-
pg_crc32 crc;
635-
TimeLineID ret;
636-
637-
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", pgdata);
638-
639-
if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
640-
{
641-
elog(WARNING, "cannot open pg_controldata file \"%s\": %s",
642-
ControlFilePath, strerror(errno));
643-
return 0;
644-
}
645-
646-
if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
647-
{
648-
elog(WARNING, "cannot read pg_controldata file \"%s\": %s",
649-
ControlFilePath, strerror(errno));
650-
return 0;
651-
}
652-
close(fd);
653-
654-
/* Check the CRC. */
655-
INIT_CRC32C(crc);
656-
COMP_CRC32C(crc,
657-
(char *) &ControlFile,
658-
offsetof(ControlFileData, crc));
659-
FIN_CRC32C(crc);
660-
661-
if (!EQ_CRC32C(crc, ControlFile.crc))
662-
{
663-
elog(WARNING, "Calculated CRC checksum does not match value stored in file.\n"
664-
"Either the file is corrupt, or it has a different layout than this program\n"
665-
"is expecting. The results below are untrustworthy.\n");
666-
return 0;
667-
}
668-
669-
if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)
670-
{
671-
elog(WARNING, "possible byte ordering mismatch\n"
672-
"The byte ordering used to store the pg_control file might not match the one\n"
673-
"used by this program. In that case the results below would be incorrect, and\n"
674-
"the PostgreSQL installation would be incompatible with this data directory.\n");
675-
return 0;
676-
}
677-
678-
ret = ControlFile.checkPointCopy.ThisTimeLineID;
679-
680-
return ret;
681-
}
682-
683626
/* get TLI of the latest full backup */
684627
static TimeLineID
685628
get_fullbackup_timeline(parray *backups, const pgRecoveryTarget *rt)

util.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,66 @@
1111

1212
#include <time.h>
1313

14+
#include "catalog/pg_control.h"
15+
16+
static void
17+
checkControlFile(ControlFileData *ControlFile)
18+
{
19+
pg_crc32c crc;
20+
21+
/* Calculate CRC */
22+
INIT_CRC32C(crc);
23+
COMP_CRC32C(crc, (char *) ControlFile, offsetof(ControlFileData, crc));
24+
FIN_CRC32C(crc);
25+
26+
/* Then compare it */
27+
if (!EQ_CRC32C(crc, ControlFile->crc))
28+
elog(ERROR_CORRUPTED, "Calculated CRC checksum does not match value stored in file.\n"
29+
"Either the file is corrupt, or it has a different layout than this program\n"
30+
"is expecting. The results below are untrustworthy.\n");
31+
32+
if (ControlFile->pg_control_version % 65536 == 0 && ControlFile->pg_control_version / 65536 != 0)
33+
elog(ERROR_CORRUPTED, "possible byte ordering mismatch\n"
34+
"The byte ordering used to store the pg_control file might not match the one\n"
35+
"used by this program. In that case the results below would be incorrect, and\n"
36+
"the PostgreSQL installation would be incompatible with this data directory.\n");
37+
}
38+
39+
/*
40+
* Verify control file contents in the buffer src, and copy it to *ControlFile.
41+
*/
42+
static void
43+
digestControlFile(ControlFileData *ControlFile, char *src, size_t size)
44+
{
45+
if (size != PG_CONTROL_SIZE)
46+
elog(ERROR_PG_INCOMPATIBLE, "unexpected control file size %d, expected %d\n",
47+
(int) size, PG_CONTROL_SIZE);
48+
49+
memcpy(ControlFile, src, sizeof(ControlFileData));
50+
51+
/* Additional checks on control file */
52+
checkControlFile(ControlFile);
53+
}
54+
55+
/*
56+
* Utility shared by backup and restore to fetch the current timeline
57+
* used by a node.
58+
*/
59+
TimeLineID
60+
get_current_timeline(void)
61+
{
62+
ControlFileData ControlFile;
63+
char *buffer;
64+
size_t size;
65+
66+
/* First fetch file... */
67+
buffer = slurpFile(pgdata, "global/pg_control", &size);
68+
digestControlFile(&ControlFile, buffer, size);
69+
pg_free(buffer);
70+
71+
return ControlFile.checkPointCopy.ThisTimeLineID;
72+
}
73+
1474
/*
1575
* Convert time_t value to ISO-8601 format string
1676
*/

0 commit comments

Comments
 (0)