1
0
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:
Michael Paquier 2016-01-15 14:09:31 +09:00
parent a5a76c14c5
commit e2bbf69403
4 changed files with 61 additions and 83 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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
View File

@ -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
*/