1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-28 09:33:54 +02:00

Begin cleanup of version-related code

Due to changes in XlogRecPtr in 9.3, older version of pg_rman are
already incompatible either way, and it is a pain to maintain code
duplicated from past versions of Postgres, so rely a maximum on the
core structures.
This commit is contained in:
Michael Paquier 2013-12-12 22:20:08 +09:00
parent 83462de39b
commit 5bc716415a
4 changed files with 54 additions and 113 deletions

View File

@ -20,17 +20,23 @@
#include "libpq/pqsignal.h"
#include "pgut/pgut-port.h"
#define TIMEOUT_ARCHIVE 10 /* wait 10 sec until WAL archive complete */
/* wait 10 sec until WAL archive complete */
#define TIMEOUT_ARCHIVE 10
/* Server version */
static int server_version = 0;
static bool in_backup = false; /* TODO: more robust logic */
static parray *cleanup_list; /* list of command to execute at error processing for snapshot */
/* List of commands to execute at error processing for snapshot */
static parray *cleanup_list;
/*
* Backup routines
*/
static void backup_cleanup(bool fatal, void *userdata);
static void delete_old_files(const char *root, parray *files, int keep_files,
int keep_days, int server_version, bool is_arclog);
static void delete_old_files(const char *root,
parray *files, int keep_files,
int keep_days, bool is_arclog);
static void backup_files(const char *from_root, const char *to_root,
parray *files, parray *prev_files, const XLogRecPtr *lsn, bool compress, const char *prefix);
static parray *do_backup_database(parray *backup_list, pgBackupOption bkupopt);
@ -710,7 +716,6 @@ do_backup(pgBackupOption bkupopt)
parray *files_database;
parray *files_arclog;
parray *files_srvlog;
int server_version;
int ret;
/* repack the necesary options */
@ -745,7 +750,7 @@ do_backup(pgBackupOption bkupopt)
#endif
/* confirm data block size and xlog block size are compatible */
server_version = get_server_version();
check_server_version();
/* setup cleanup callback function */
in_backup = true;
@ -837,10 +842,10 @@ do_backup(pgBackupOption bkupopt)
*/
if (HAVE_ARCLOG(&current))
delete_old_files(arclog_path, files_arclog, keep_arclog_files,
keep_arclog_days, server_version, true);
keep_arclog_days, true);
if (current.with_serverlog)
delete_old_files(srvlog_path, files_srvlog, keep_srvlog_files,
keep_srvlog_days, server_version, false);
keep_srvlog_days, false);
/* Delete old backup files after all backup operation. */
pgBackupDelete(keep_data_generations, keep_data_days);
@ -951,15 +956,14 @@ make_backup_label(parray *backup_list)
/*
* get server version and confirm block sizes.
*/
int
get_server_version(void)
void
check_server_version(void)
{
static int server_version = 0;
bool my_conn;
/* return cached server version */
/* Leave if server has already been checked */
if (server_version > 0)
return server_version;
return;
my_conn = (connection == NULL);
@ -968,22 +972,19 @@ get_server_version(void)
/* confirm server version */
server_version = PQserverVersion(connection);
if (server_version < 80200)
if (server_version != PG_VERSION_NUM)
elog(ERROR_PG_INCOMPATIBLE,
_("server version is %d.%d.%d, but must be 8.2 or higher."),
server_version / 10000,
(server_version / 100) % 100,
server_version % 100);
_("server version is %d.%d.%d, must be %s or higher."),
server_version / 10000,
(server_version / 100) % 100,
server_version % 100, PG_MAJORVERSION);
/* confirm block_size (BLCKSZ) and wal_block_size (XLOG_BLCKSZ) */
confirm_block_size("block_size", BLCKSZ);
if (server_version >= 80400)
confirm_block_size("wal_block_size", XLOG_BLCKSZ);
confirm_block_size("wal_block_size", XLOG_BLCKSZ);
if (my_conn)
disconnect();
return server_version;
}
static void
@ -1013,25 +1014,15 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
{
PGresult *res;
const char *params[2];
int server_version;
params[0] = label;
reconnect();
server_version = get_server_version();
if (server_version >= 80400)
{
/* 2nd argument is 'fast'*/
params[1] = smooth ? "false" : "true";
res = execute("SELECT * from pg_xlogfile_name_offset(pg_start_backup($1, $2))", 2, params);
}
else
{
/* v8.3 always uses smooth checkpoint */
if (!smooth && server_version >= 80300)
command("CHECKPOINT", 0, NULL);
res = execute("SELECT * from pg_xlogfile_name_offset(pg_start_backup($1))", 1, params);
}
/* 2nd argument is 'fast'*/
params[1] = smooth ? "false" : "true";
res = execute("SELECT * from pg_xlogfile_name_offset(pg_start_backup($1, $2))", 2, params);
if (backup != NULL)
get_lsn(res, &backup->tli, &backup->start_lsn);
PQclear(res);
@ -1419,7 +1410,6 @@ delete_old_files(const char *root,
parray *files,
int keep_files,
int keep_days,
int server_version,
bool is_arclog)
{
int i;
@ -1460,7 +1450,7 @@ delete_old_files(const char *root,
elog(LOG, "%s() %s", __FUNCTION__, file->path);
/* Delete completed WALs only. */
if (is_arclog && !xlog_is_complete_wal(file, server_version))
if (is_arclog && !xlog_is_complete_wal(file))
{
elog(LOG, "%s() not complete WAL", __FUNCTION__);
continue;

79
data.c
View File

@ -18,10 +18,6 @@
#include "storage/block.h"
#include "storage/bufpage.h"
#if PG_VERSION_NUM < 80300
#define XLogRecPtrIsInvalid(r) ((r).xrecoff == 0)
#endif
#ifdef HAVE_LIBZ
#include <zlib.h>
@ -156,10 +152,6 @@ doInflate(z_stream *zp, size_t in_size, size_t out_size,void *inbuf,
}
#endif
#define PG_PAGE_LAYOUT_VERSION_v80 2 /* 8.0 */
#define PG_PAGE_LAYOUT_VERSION_v81 3 /* 8.1 - 8.2 */
#define PG_PAGE_LAYOUT_VERSION_v83 4 /* 8.3 - */
/* 80000 <= PG_VERSION_NUM < 80300 */
typedef struct PageHeaderData_v80
{
@ -201,9 +193,8 @@ typedef struct PageHeaderData_v83
typedef union DataPage
{
PageHeaderData_v80 v80; /* 8.0 - 8.2 */
PageHeaderData_v83 v83; /* 8.3 - */
char data[BLCKSZ];
PageHeaderData page_data;
char data[BLCKSZ];
} DataPage;
typedef struct BackupPageHeader
@ -214,56 +205,27 @@ typedef struct BackupPageHeader
} BackupPageHeader;
static bool
parse_page(const DataPage *page, int server_version,
parse_page(const DataPage *page,
XLogRecPtr *lsn, uint16 *offset, uint16 *length)
{
uint16 page_layout_version;
const PageHeaderData *page_data = &page->page_data;
/* Determine page layout version */
if (server_version < 80100)
page_layout_version = PG_PAGE_LAYOUT_VERSION_v80;
else if (server_version < 80300)
page_layout_version = PG_PAGE_LAYOUT_VERSION_v81;
else
page_layout_version = PG_PAGE_LAYOUT_VERSION_v83;
/* Get lsn from page header */
*lsn = PageXLogRecPtrGet(page_data->pd_lsn);
/* Check normal case */
if (server_version < 80300)
if (PageGetPageSize(page_data) == BLCKSZ &&
PageGetPageLayoutVersion(page_data) == PG_PAGE_LAYOUT_VERSION &&
(page_data->pd_flags & ~PD_VALID_FLAG_BITS) == 0 &&
page_data->pd_lower >= SizeOfPageHeaderData &&
page_data->pd_lower <= page_data->pd_upper &&
page_data->pd_upper <= page_data->pd_special &&
page_data->pd_special <= BLCKSZ &&
page_data->pd_special == MAXALIGN(page_data->pd_special) &&
!XLogRecPtrIsInvalid(*lsn))
{
const PageHeaderData_v80 *v80 = &page->v80;
if (PageGetPageSize_v80(v80) == BLCKSZ &&
PageGetPageLayoutVersion_v80(v80) == page_layout_version &&
v80->pd_lower >= SizeOfPageHeaderData_v80 &&
v80->pd_lower <= v80->pd_upper &&
v80->pd_upper <= v80->pd_special &&
v80->pd_special <= BLCKSZ &&
v80->pd_special == MAXALIGN(v80->pd_special) &&
!XLogRecPtrIsInvalid(*lsn = v80->pd_lsn))
{
*offset = v80->pd_lower;
*length = v80->pd_upper - v80->pd_lower;
return true;
}
}
else
{
const PageHeaderData_v83 *v83 = &page->v83;
if (PageGetPageSize_v83(v83) == BLCKSZ &&
PageGetPageLayoutVersion_v83(v83) == page_layout_version &&
(v83->pd_flags & ~PD_VALID_FLAG_BITS_v83) == 0 &&
v83->pd_lower >= SizeOfPageHeaderData_v83 &&
v83->pd_lower <= v83->pd_upper &&
v83->pd_upper <= v83->pd_special &&
v83->pd_special <= BLCKSZ &&
v83->pd_special == MAXALIGN(v83->pd_special) &&
!XLogRecPtrIsInvalid(*lsn = v83->pd_lsn))
{
*offset = v83->pd_lower;
*length = v83->pd_upper - v83->pd_lower;
return true;
}
*offset = page_data->pd_lower;
*length = page_data->pd_upper - page_data->pd_lower;
return true;
}
*offset = *length = 0;
@ -289,7 +251,6 @@ backup_data_file(const char *from_root, const char *to_root,
size_t read_len;
int errno_tmp;
pg_crc32 crc;
int server_version;
#ifdef HAVE_LIBZ
z_stream z;
char outbuf[zlibOutSize];
@ -351,7 +312,7 @@ backup_data_file(const char *from_root, const char *to_root,
#endif
/* confirm server version */
server_version = get_server_version();
check_server_version();
/* read each page and write the page excluding hole */
for (blknum = 0;
@ -368,7 +329,7 @@ backup_data_file(const char *from_root, const char *to_root,
* If a invalid data page was found, fallback to simple copy to ensure
* all pages in the file don't have BackupPageHeader.
*/
if (!parse_page(&page, server_version, &page_lsn,
if (!parse_page(&page, &page_lsn,
&header.hole_offset, &header.hole_length))
{
elog(LOG, "%s fall back to simple copy", file->path);

View File

@ -20,16 +20,8 @@
#include "utils/pg_crc.h"
#include "parray.h"
#if PG_VERSION_NUM < 80200
#define XLOG_BLCKSZ BLCKSZ
#endif
#if PG_VERSION_NUM < 80300
#define TXID_CURRENT_SQL "SELECT transactionid FROM pg_locks WHERE locktype = 'transactionid' AND pid = pg_backend_pid();"
#include <sys/stat.h>
#else
/* Query to fetch current transaction ID */
#define TXID_CURRENT_SQL "SELECT txid_current();"
#endif
/* Directory/File names */
#define DATABASE_DIR "database"
@ -241,7 +233,7 @@ extern const char *pgdata_exclude[];
/* in backup.c */
extern int do_backup(pgBackupOption bkupopt);
extern BackupMode parse_backup_mode(const char *value, int elevel);
extern int get_server_version(void);
extern void check_server_version(void);
extern bool fileExists(const char *path);
/* in restore.c */
@ -306,7 +298,7 @@ extern int pgFileCompareMtime(const void *f1, const void *f2);
extern int pgFileCompareMtimeDesc(const void *f1, const void *f2);
/* in xlog.c */
extern bool xlog_is_complete_wal(const pgFile *file, int server_version);
extern bool xlog_is_complete_wal(const pgFile *file);
extern void xlog_fname(char *fname, size_t len, TimeLineID tli, XLogRecPtr *lsn);
/* in data.c */

6
xlog.c
View File

@ -14,10 +14,8 @@
#include <sys/stat.h>
#include <unistd.h>
#if PG_VERSION_NUM >= 80400
typedef unsigned long Datum;
typedef struct MemoryContextData *MemoryContext;
#endif
#include "access/xlog_internal.h"
@ -37,7 +35,7 @@ typedef union XLogPage
* based on ValidXLOGHeader() in src/backend/access/transam/xlog.c.
*/
bool
xlog_is_complete_wal(const pgFile *file, int server_version)
xlog_is_complete_wal(const pgFile *file)
{
FILE *fp;
XLogPage page;
@ -61,7 +59,7 @@ xlog_is_complete_wal(const pgFile *file, int server_version)
return false;
if (page.lheader.xlp_seg_size != XLogSegSize)
return false;
if (server_version >= 80300 && page.lheader.xlp_xlog_blcksz != XLOG_BLCKSZ)
if (page.lheader.xlp_xlog_blcksz != XLOG_BLCKSZ)
return false;
/*