mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-01-09 14:45:47 +02:00
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.
This commit is contained in:
parent
a5a76c14c5
commit
e2bbf69403
26
backup.c
26
backup.c
@ -17,7 +17,6 @@
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "catalog/pg_control.h"
|
||||
#include "libpq/pqsignal.h"
|
||||
#include "pgut/pgut-port.h"
|
||||
|
||||
@ -54,7 +53,6 @@ static void create_file_list(parray *files,
|
||||
const char *subdir,
|
||||
const char *prefix,
|
||||
bool is_append);
|
||||
static TimeLineID get_current_timeline(void);
|
||||
|
||||
/*
|
||||
* Take a backup of database and return the list of files backed up.
|
||||
@ -1047,27 +1045,3 @@ create_file_list(parray *files,
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan control file of given cluster at obtain the current timeline
|
||||
* since last checkpoint that occurred on it.
|
||||
*/
|
||||
static TimeLineID
|
||||
get_current_timeline(void)
|
||||
{
|
||||
char *buffer;
|
||||
size_t size;
|
||||
ControlFileData control_file;
|
||||
|
||||
/* First fetch file... */
|
||||
buffer = slurpFile(pgdata, "global/pg_control", &size);
|
||||
|
||||
/* .. Then interpret it */
|
||||
if (size != PG_CONTROL_SIZE)
|
||||
elog(ERROR_CORRUPTED, "unexpected control file size %d, expected %d",
|
||||
(int) size, PG_CONTROL_SIZE);
|
||||
memcpy(&control_file, buffer, sizeof(ControlFileData));
|
||||
|
||||
/* Finally return the timeline wanted */
|
||||
return control_file.checkPointCopy.ThisTimeLineID;
|
||||
}
|
||||
|
@ -289,6 +289,7 @@ extern bool copy_file(const char *from_root, const char *to_root,
|
||||
pgFile *file);
|
||||
|
||||
/* in util.c */
|
||||
extern TimeLineID get_current_timeline(void);
|
||||
extern void time2iso(char *buf, size_t len, time_t time);
|
||||
extern const char *status2str(BackupStatus status);
|
||||
extern void remove_trailing_space(char *buf, int comment_mark);
|
||||
|
57
restore.c
57
restore.c
@ -29,7 +29,6 @@ static parray * readTimeLineHistory(TimeLineID targetTLI);
|
||||
static bool satisfy_timeline(const parray *timelines, const pgBackup *backup);
|
||||
static bool satisfy_recovery_target(const pgBackup *backup,
|
||||
const pgRecoveryTarget *rt);
|
||||
static TimeLineID get_current_timeline(void);
|
||||
static TimeLineID get_fullbackup_timeline(parray *backups,
|
||||
const pgRecoveryTarget *rt);
|
||||
static void print_backup_lsn(const pgBackup *backup);
|
||||
@ -624,62 +623,6 @@ satisfy_timeline(const parray *timelines, const pgBackup *backup)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* get TLI of the current database */
|
||||
static TimeLineID
|
||||
get_current_timeline(void)
|
||||
{
|
||||
ControlFileData ControlFile;
|
||||
int fd;
|
||||
char ControlFilePath[MAXPGPATH];
|
||||
pg_crc32 crc;
|
||||
TimeLineID ret;
|
||||
|
||||
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", pgdata);
|
||||
|
||||
if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
|
||||
{
|
||||
elog(WARNING, "cannot open pg_controldata file \"%s\": %s",
|
||||
ControlFilePath, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
|
||||
{
|
||||
elog(WARNING, "cannot read pg_controldata file \"%s\": %s",
|
||||
ControlFilePath, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* Check the CRC. */
|
||||
INIT_CRC32C(crc);
|
||||
COMP_CRC32C(crc,
|
||||
(char *) &ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32C(crc);
|
||||
|
||||
if (!EQ_CRC32C(crc, ControlFile.crc))
|
||||
{
|
||||
elog(WARNING, "Calculated CRC checksum does not match value stored in file.\n"
|
||||
"Either the file is corrupt, or it has a different layout than this program\n"
|
||||
"is expecting. The results below are untrustworthy.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)
|
||||
{
|
||||
elog(WARNING, "possible byte ordering mismatch\n"
|
||||
"The byte ordering used to store the pg_control file might not match the one\n"
|
||||
"used by this program. In that case the results below would be incorrect, and\n"
|
||||
"the PostgreSQL installation would be incompatible with this data directory.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ControlFile.checkPointCopy.ThisTimeLineID;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get TLI of the latest full backup */
|
||||
static TimeLineID
|
||||
get_fullbackup_timeline(parray *backups, const pgRecoveryTarget *rt)
|
||||
|
60
util.c
60
util.c
@ -11,6 +11,66 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "catalog/pg_control.h"
|
||||
|
||||
static void
|
||||
checkControlFile(ControlFileData *ControlFile)
|
||||
{
|
||||
pg_crc32c crc;
|
||||
|
||||
/* Calculate CRC */
|
||||
INIT_CRC32C(crc);
|
||||
COMP_CRC32C(crc, (char *) ControlFile, offsetof(ControlFileData, crc));
|
||||
FIN_CRC32C(crc);
|
||||
|
||||
/* Then compare it */
|
||||
if (!EQ_CRC32C(crc, ControlFile->crc))
|
||||
elog(ERROR_CORRUPTED, "Calculated CRC checksum does not match value stored in file.\n"
|
||||
"Either the file is corrupt, or it has a different layout than this program\n"
|
||||
"is expecting. The results below are untrustworthy.\n");
|
||||
|
||||
if (ControlFile->pg_control_version % 65536 == 0 && ControlFile->pg_control_version / 65536 != 0)
|
||||
elog(ERROR_CORRUPTED, "possible byte ordering mismatch\n"
|
||||
"The byte ordering used to store the pg_control file might not match the one\n"
|
||||
"used by this program. In that case the results below would be incorrect, and\n"
|
||||
"the PostgreSQL installation would be incompatible with this data directory.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify control file contents in the buffer src, and copy it to *ControlFile.
|
||||
*/
|
||||
static void
|
||||
digestControlFile(ControlFileData *ControlFile, char *src, size_t size)
|
||||
{
|
||||
if (size != PG_CONTROL_SIZE)
|
||||
elog(ERROR_PG_INCOMPATIBLE, "unexpected control file size %d, expected %d\n",
|
||||
(int) size, PG_CONTROL_SIZE);
|
||||
|
||||
memcpy(ControlFile, src, sizeof(ControlFileData));
|
||||
|
||||
/* Additional checks on control file */
|
||||
checkControlFile(ControlFile);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility shared by backup and restore to fetch the current timeline
|
||||
* used by a node.
|
||||
*/
|
||||
TimeLineID
|
||||
get_current_timeline(void)
|
||||
{
|
||||
ControlFileData ControlFile;
|
||||
char *buffer;
|
||||
size_t size;
|
||||
|
||||
/* First fetch file... */
|
||||
buffer = slurpFile(pgdata, "global/pg_control", &size);
|
||||
digestControlFile(&ControlFile, buffer, size);
|
||||
pg_free(buffer);
|
||||
|
||||
return ControlFile.checkPointCopy.ThisTimeLineID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert time_t value to ISO-8601 format string
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user