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

Fix a critical bug that pg_rman cannot restore database from incremental backup. Backup itself worked correctly, but restore command broke database files.

git-svn-id: http://pg-rman.googlecode.com/svn/trunk@25 182aca00-e38e-11de-a668-6fd11605f5ce
This commit is contained in:
itagaki.takahiro 2009-12-22 07:36:31 +00:00
parent bc5717b1e0
commit 59d0911fa7
9 changed files with 193 additions and 194 deletions

View File

@ -30,7 +30,7 @@ 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 backup_files(const char *from_root, const char *to_root,
parray *files, parray *prev_files, XLogRecPtr *lsn, bool compress_data);
parray *files, parray *prev_files, const XLogRecPtr *lsn, bool compress);
static parray *do_backup_database(parray *backup_list, bool smooth_checkpoint);
static parray *do_backup_arclog(parray *backup_list);
static parray *do_backup_srvlog(parray *backup_list);
@ -137,7 +137,7 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
files = parray_new();
dir_list_file(files, pgdata, pgdata_exclude, true, false);
/* mark files as 'datafile' which are under base/global/pg_tblspc */
/* mark files that are possible datafile as 'datafile' */
for (i = 0; i < parray_num(files); i++)
{
pgFile *file = (pgFile *) parray_get(files, i);
@ -148,7 +148,7 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
if (!S_ISREG(file->mode))
continue;
/* data files are under base/global/pg_tblspc */
/* data files are under "base", "global", or "pg_tblspc" */
relative = file->path + strlen(pgdata) + 1;
if (!path_is_prefix_of_path("base", relative) &&
!path_is_prefix_of_path("global", relative) &&
@ -214,16 +214,16 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
static parray *
do_backup_arclog(parray *backup_list)
{
int i;
parray *files;
parray *prev_files = NULL; /* file list of previous database backup */
FILE *fp;
char path[MAXPGPATH];
char timeline_dir[MAXPGPATH];
char prev_file_txt[MAXPGPATH];
pgBackup *prev_backup;
int64 arclog_write_bytes = 0;
char last_wal[MAXPGPATH];
int i;
parray *files;
parray *prev_files = NULL; /* file list of previous database backup */
FILE *fp;
char path[MAXPGPATH];
char timeline_dir[MAXPGPATH];
char prev_file_txt[MAXPGPATH];
pgBackup *prev_backup;
int64 arclog_write_bytes = 0;
char last_wal[MAXPGPATH];
if (!HAVE_ARCLOG(&current))
return NULL;
@ -345,14 +345,14 @@ do_backup_arclog(parray *backup_list)
static parray *
do_backup_srvlog(parray *backup_list)
{
int i;
parray *files;
parray *prev_files = NULL; /* file list of previous database backup */
FILE *fp;
char path[MAXPGPATH];
char prev_file_txt[MAXPGPATH];
pgBackup *prev_backup;
int64 srvlog_write_bytes = 0;
int i;
parray *files;
parray *prev_files = NULL; /* file list of previous database backup */
FILE *fp;
char path[MAXPGPATH];
char prev_file_txt[MAXPGPATH];
pgBackup *prev_backup;
int64 srvlog_write_bytes = 0;
if (!current.with_serverlog)
return NULL;
@ -818,10 +818,14 @@ backup_cleanup(bool fatal, void *userdata)
/* take incremental backup. */
static void
backup_files(const char *from_root, const char *to_root, parray *files,
parray *prev_files, XLogRecPtr *lsn, bool compress_data)
backup_files(const char *from_root,
const char *to_root,
parray *files,
parray *prev_files,
const XLogRecPtr *lsn,
bool compress)
{
int i;
int i;
struct timeval tv;
/* sort pathname ascending */
@ -832,8 +836,9 @@ backup_files(const char *from_root, const char *to_root, parray *files,
/* backup a file or create a directory */
for (i = 0; i < parray_num(files); i++)
{
int ret;
struct stat buf;
int ret;
struct stat buf;
pgFile *file = (pgFile *) parray_get(files, i);
/* check for interrupt */
@ -869,6 +874,7 @@ backup_files(const char *from_root, const char *to_root, parray *files,
if (S_ISDIR(buf.st_mode))
{
char dirpath[MAXPGPATH];
snprintf(dirpath, lengthof(dirpath), "%s/%s", to_root,
file->path + strlen(from_root) + 1);
if (!check)
@ -918,7 +924,7 @@ backup_files(const char *from_root, const char *to_root, parray *files,
/* copy the file into backup */
if (file->is_datafile)
{
backup_data_file(from_root, to_root, file, lsn, compress_data);
backup_data_file(from_root, to_root, file, lsn, compress);
if (file->write_size == 0 && file->read_size > 0)
{
/* record as skipped file in file_xxx.txt */
@ -930,7 +936,7 @@ backup_files(const char *from_root, const char *to_root, parray *files,
}
else
copy_file(from_root, to_root, file,
compress_data ? COMPRESSION : NO_COMPRESSION);
compress ? COMPRESSION : NO_COMPRESSION);
if (verbose)
{
@ -965,11 +971,10 @@ delete_old_files(const char *root,
int server_version,
bool is_arclog)
{
int i;
int j;
int file_num = 0;
time_t days_threashold =
current.start_time - (keep_days * 60 * 60 * 24);
int i;
int j;
int file_num = 0;
time_t days_threshold = current.start_time - (keep_days * 60 * 60 * 24);
if (verbose)
{
@ -990,7 +995,7 @@ delete_old_files(const char *root,
root, files_str, days_str);
}
/* delete files which satisfy both condition */
/* delete files which satisfy both conditions */
if (keep_files == KEEP_INFINITE || keep_days == KEEP_INFINITE)
{
elog(LOG, "%s() infinite", __FUNCTION__);
@ -1003,7 +1008,7 @@ delete_old_files(const char *root,
pgFile *file = (pgFile *) parray_get(files, i);
elog(LOG, "%s() %s", __FUNCTION__, file->path);
/* Delete complete WAL only. */
/* Delete completed WALs only. */
if (is_arclog && !xlog_is_complete_wal(file, server_version))
{
elog(LOG, "%s() not complete WAL", __FUNCTION__);
@ -1013,17 +1018,17 @@ delete_old_files(const char *root,
file_num++;
/*
* If the mtime of the file is older than the threashold and there are
* If the mtime of the file is older than the threshold and there are
* enough number of files newer than the files, delete the file.
*/
if (file->mtime >= days_threashold)
if (file->mtime >= days_threshold)
{
elog(LOG, "%s() %lu is not older than %lu", __FUNCTION__,
file->mtime, days_threashold);
file->mtime, days_threshold);
continue;
}
elog(LOG, "%s() %lu is older than %lu", __FUNCTION__,
file->mtime, days_threashold);
file->mtime, days_threshold);
if (file_num <= keep_files)
{
@ -1035,7 +1040,7 @@ delete_old_files(const char *root,
if (verbose)
printf(_("delete \"%s\"\n"), file->path + strlen(root) + 1);
/* delete corresponding backup history file if any */
/* delete corresponding backup history file if exists */
file = (pgFile *) parray_remove(files, i);
for (j = parray_num(files) - 1; j >= 0; j--)
{

View File

@ -247,8 +247,8 @@ err_proc:
pgBackup *
catalog_get_last_data_backup(parray *backup_list)
{
int i;
pgBackup *backup = NULL;
int i;
pgBackup *backup = NULL;
/* backup_list is sorted in order of descending ID */
for (i = 0; i < parray_num(backup_list); i++)
@ -269,8 +269,8 @@ catalog_get_last_data_backup(parray *backup_list)
pgBackup *
catalog_get_last_arclog_backup(parray *backup_list)
{
int i;
pgBackup *backup = NULL;
int i;
pgBackup *backup = NULL;
/* backup_list is sorted in order of descending ID */
for (i = 0; i < parray_num(backup_list); i++)

122
data.c
View File

@ -261,7 +261,8 @@ parse_page(const DataPage *page, int server_version,
return true;
}
}
*offset = *length = 0;
return false;
}
@ -273,7 +274,7 @@ parse_page(const DataPage *page, int server_version,
*/
void
backup_data_file(const char *from_root, const char *to_root,
pgFile *file, const XLogRecPtr *lsn, bool compress_data)
pgFile *file, const XLogRecPtr *lsn, bool compress)
{
char to_path[MAXPGPATH];
FILE *in;
@ -324,7 +325,7 @@ backup_data_file(const char *from_root, const char *to_root,
file->write_size = 0;
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
@ -366,7 +367,7 @@ backup_data_file(const char *from_root, const char *to_root,
fclose(out);
file->is_datafile = false;
copy_file(from_root, to_root, file,
compress_data ? COMPRESSION : NO_COMPRESSION);
compress ? COMPRESSION : NO_COMPRESSION);
return;
}
@ -380,7 +381,7 @@ backup_data_file(const char *from_root, const char *to_root,
upper_length = BLCKSZ - upper_offset;
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
doDeflate(&z, sizeof(header), sizeof(outbuf), &header, outbuf, in,
out, &crc, &file->write_size, Z_NO_FLUSH);
@ -444,7 +445,7 @@ backup_data_file(const char *from_root, const char *to_root,
header.hole_length = 0;
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
doDeflate(&z, sizeof(header), sizeof(outbuf), &header, outbuf,
in, out, &crc, &file->write_size, Z_NO_FLUSH);
@ -469,7 +470,7 @@ backup_data_file(const char *from_root, const char *to_root,
/* write odd size page image */
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
doDeflate(&z, read_len, sizeof(outbuf), page.data, outbuf, in, out,
&crc, &file->write_size, Z_NO_FLUSH);
@ -495,7 +496,7 @@ backup_data_file(const char *from_root, const char *to_root,
}
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
if (file->read_size > 0)
{
@ -512,9 +513,12 @@ backup_data_file(const char *from_root, const char *to_root,
elog(ERROR_SYSTEM, _("can't close compression stream: %s"), z.msg);
}
}
#endif
/* update file permission */
/*
* update file permission
* FIXME: Should set permission on open?
*/
if (!check && chmod(to_path, FILE_PERMISSION) == -1)
{
int errno_tmp = errno;
@ -551,26 +555,29 @@ backup_data_file(const char *from_root, const char *to_root,
* same relative path.
*/
void
restore_data_file(const char *from_root, const char *to_root, pgFile *file, bool compress_data)
restore_data_file(const char *from_root,
const char *to_root,
pgFile *file,
bool compress)
{
char to_path[MAXPGPATH];
FILE *in;
FILE *out;
BackupPageHeader header;
BlockNumber blknum;
char to_path[MAXPGPATH];
FILE *in;
FILE *out;
BackupPageHeader header;
BlockNumber blknum;
#ifdef HAVE_LIBZ
z_stream z;
int status;
char inbuf[zlibInSize];
pg_crc32 crc;
size_t read_size;
z_stream z;
int status;
char inbuf[zlibInSize];
pg_crc32 crc;
size_t read_size;
#endif
/* If the file is not a datafile, copy it. */
/* If the file is not a datafile, just copy it. */
if (!file->is_datafile)
{
copy_file(from_root, to_root, file,
compress_data ? DECOMPRESSION : NO_COMPRESSION);
compress ? DECOMPRESSION : NO_COMPRESSION);
return;
}
@ -582,10 +589,16 @@ restore_data_file(const char *from_root, const char *to_root, pgFile *file, bool
strerror(errno));
}
/* open backup file for write */
/*
* Open backup file for write. We use "r+" at first to overwrite only
* modified pages for incremental restore. If the file is not exists,
* re-open it with "w" to create an empty file.
*/
snprintf(to_path, lengthof(to_path), "%s/%s", to_root,
file->path + strlen(from_root) + 1);
out = fopen(to_path, "w");
out = fopen(to_path, "r+");
if (out == NULL && errno == ENOENT)
out = fopen(to_path, "w");
if (out == NULL)
{
int errno_tmp = errno;
@ -595,7 +608,7 @@ restore_data_file(const char *from_root, const char *to_root, pgFile *file, bool
}
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
@ -611,16 +624,16 @@ restore_data_file(const char *from_root, const char *to_root, pgFile *file, bool
}
#endif
for (blknum = 0; ;blknum++)
for (blknum = 0; ; blknum++)
{
size_t read_len;
DataPage page; /* used as read buffer */
int upper_offset;
int upper_length;
size_t read_len;
DataPage page; /* used as read buffer */
int upper_offset;
int upper_length;
/* read BackupPageHeader */
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
status = doInflate(&z, sizeof(inbuf), sizeof(header), inbuf,
&header, in, out, &crc, &read_size);
@ -669,14 +682,15 @@ restore_data_file(const char *from_root, const char *to_root, pgFile *file, bool
/* read lower/upper into page.data and restore hole */
memset(page.data + header.hole_offset, 0, header.hole_length);
#ifdef HAVE_LIBZ
if (compress_data)
if (compress)
{
elog(LOG, "\n%s() %s %d %d", __FUNCTION__, file->path, header.hole_offset, upper_length);
if (header.hole_offset > 0)
{
doInflate(&z, sizeof(inbuf), header.hole_offset, inbuf, page.data,
in, out, &crc, &read_size);
doInflate(&z, sizeof(inbuf), header.hole_offset, inbuf,
page.data, in, out, &crc, &read_size);
if (z.avail_out != 0)
elog(ERROR_SYSTEM, _("can't read block %u of \"%s\""),
blknum, file->path);
@ -702,25 +716,21 @@ restore_data_file(const char *from_root, const char *to_root, pgFile *file, bool
}
}
/* by the incremental backup, we skip in a page without the update. */
if (blknum != header.block)
{
if (fseek(out, (header.block - blknum) * BLCKSZ, SEEK_CUR) < 0)
elog(ERROR_SYSTEM, _("can't seek restore target file \"%s\": %s"),
to_path, strerror(errno));
blknum = header.block;
}
/*
* Seek and write the restored page. Backup might have holes in
* incremental backups.
*/
blknum = header.block;
if (fseek(out, blknum * BLCKSZ, SEEK_SET) < 0)
elog(ERROR_SYSTEM, _("can't seek block %u of \"%s\": %s"),
blknum, to_path, strerror(errno));
if (fwrite(page.data, 1, sizeof(page), out) != sizeof(page))
{
elog(ERROR_SYSTEM, _("can't write block %u of \"%s\": %s"),
blknum, file->path, strerror(errno));
}
}
#ifdef HAVE_LIBZ
if (compress_data && inflateEnd(&z) != Z_OK)
if (compress && inflateEnd(&z) != Z_OK)
elog(ERROR_SYSTEM, _("can't close compression stream: %s"), z.msg);
#endif
@ -742,14 +752,14 @@ void
copy_file(const char *from_root, const char *to_root, pgFile *file,
CompressionMode mode)
{
char to_path[MAXPGPATH];
FILE *in;
FILE *out;
size_t read_len = 0;
int errno_tmp;
char buf[8192];
struct stat st;
pg_crc32 crc;
char to_path[MAXPGPATH];
FILE *in;
FILE *out;
size_t read_len = 0;
int errno_tmp;
char buf[8192];
struct stat st;
pg_crc32 crc;
#ifdef HAVE_LIBZ
z_stream z;
int status;

View File

@ -74,7 +74,7 @@ pgBackupDelete(int keep_generations, int keep_days)
int i;
parray *backup_list;
int backup_num;
time_t days_threashold = current.start_time - (keep_days * 60 * 60 * 24);
time_t days_threshold = current.start_time - (keep_days * 60 * 60 * 24);
if (verbose)
{
@ -130,18 +130,18 @@ pgBackupDelete(int keep_generations, int keep_days)
}
/*
* If the start time of the backup is older than the threashold and
* If the start time of the backup is older than the threshold and
* there are enough generations of full backups, delete the backup.
*/
if (backup->start_time >= days_threashold)
if (backup->start_time >= days_threshold)
{
elog(LOG, "%s() %lu is not older than %lu", __FUNCTION__,
backup->start_time, days_threashold);
backup->start_time, days_threshold);
continue;
}
elog(LOG, "%s() %lu is older than %lu", __FUNCTION__,
backup->start_time, days_threashold);
backup->start_time, days_threshold);
/* delete backup and update status to DELETED */
pgBackupDeleteFiles(backup);

73
dir.c
View File

@ -56,8 +56,8 @@ dir_create_dir(const char *dir, mode_t mode)
static pgFile *
pgFileNew(const char *path, bool omit_symlink)
{
struct stat st;
pgFile *file;
struct stat st;
pgFile *file;
/* stat the file */
if ((omit_symlink ? stat(path, &st) : lstat(path, &st)) == -1)
@ -84,28 +84,6 @@ pgFileNew(const char *path, bool omit_symlink)
return file;
}
void
pgFileDump(pgFile *file, FILE *out)
{
char mtime_str[100];
fprintf(out, "=================\n");
if (file)
{
time2iso(mtime_str, 100, file->mtime);
fprintf(out, "mtime=%lu(%s)\n", file->mtime, mtime_str);
fprintf(out, "size=" UINT64_FORMAT "\n", (uint64)file->size);
fprintf(out, "read_size=" UINT64_FORMAT "\n", (uint64)file->read_size);
fprintf(out, "write_size=" UINT64_FORMAT "\n", (uint64)file->write_size);
fprintf(out, "mode=0%o\n", file->mode);
fprintf(out, "crc=%u\n", file->crc);
fprintf(out, "is_datafile=%s\n", file->is_datafile ? "true" : "false");
fprintf(out, "linked=\"%s\"\n", file->linked ? file->linked : "nil");
fprintf(out, "path=\"%s\"\n", file->path);
}
fprintf(out, "=================\n");
}
/*
* Delete file pointed by the pgFile.
* If the pgFile points directory, the directory must be empty.
@ -141,11 +119,11 @@ delete_file:
pg_crc32
pgFileGetCRC(pgFile *file)
{
FILE *fp;
pg_crc32 crc = 0;
char buf[1024];
size_t len;
int errno_tmp;
FILE *fp;
pg_crc32 crc = 0;
char buf[1024];
size_t len;
int errno_tmp;
/* open file in binary read mode */
fp = fopen(file->path, "r");
@ -211,7 +189,8 @@ pgFileCompareMtime(const void *f1, const void *f2)
return 1;
else if (f1p->mtime < f2p->mtime)
return -1;
else return 0;
else
return 0;
}
/* Compare two pgFile with their modify timestamp in descending order. */
@ -287,11 +266,11 @@ dir_list_file(parray *files, const char *root, const char *exclude[], bool omit_
*/
while (S_ISDIR(file->mode))
{
int i;
bool skip = false;
DIR *dir;
struct dirent *dent;
char *dirname;
int i;
bool skip = false;
DIR *dir;
struct dirent *dent;
char *dirname;
/* skip entry which matches exclude list */
dirname = strrchr(file->path, '/');
@ -566,3 +545,27 @@ dir_copy_files(const char *from_root, const char *to_root)
parray_walk(files, pgFileFree);
parray_free(files);
}
#ifdef NOT_USED
void
pgFileDump(pgFile *file, FILE *out)
{
char mtime_str[100];
fprintf(out, "=================\n");
if (file)
{
time2iso(mtime_str, 100, file->mtime);
fprintf(out, "mtime=%lu(%s)\n", file->mtime, mtime_str);
fprintf(out, "size=" UINT64_FORMAT "\n", (uint64)file->size);
fprintf(out, "read_size=" UINT64_FORMAT "\n", (uint64)file->read_size);
fprintf(out, "write_size=" UINT64_FORMAT "\n", (uint64)file->write_size);
fprintf(out, "mode=0%o\n", file->mode);
fprintf(out, "crc=%u\n", file->crc);
fprintf(out, "is_datafile=%s\n", file->is_datafile ? "true" : "false");
fprintf(out, "linked=\"%s\"\n", file->linked ? file->linked : "nil");
fprintf(out, "path=\"%s\"\n", file->path);
}
fprintf(out, "=================\n");
}
#endif

View File

@ -235,7 +235,6 @@ extern parray *dir_read_file_list(const char *root, const char *file_txt);
extern int dir_create_dir(const char *path, mode_t mode);
extern void dir_copy_files(const char *from_root, const char *to_root);
extern void pgFileDump(pgFile *file, FILE *out);
extern void pgFileDelete(pgFile *file);
extern void pgFileFree(void *file);
extern pg_crc32 pgFileGetCRC(pgFile *file);

View File

@ -156,9 +156,7 @@ do_restore(const char *target_time,
}
#endif
if (satisfy_timeline(timelines, base_backup))
{
goto base_backup_found;
}
}
/* no full backup found, can't restore */
elog(ERROR_NO_BACKUP, _("no full backup found, can't restore."));
@ -291,12 +289,12 @@ base_backup_found:
void
restore_database(pgBackup *backup)
{
char timestamp[100];
char path[MAXPGPATH];
char list_path[MAXPGPATH];
int ret;
char timestamp[100];
char path[MAXPGPATH];
char list_path[MAXPGPATH];
int ret;
parray *files;
int i;
int i;
/* confirm block size compatibility */
if (backup->block_size != BLCKSZ)

View File

@ -20,7 +20,7 @@ static bool pgBackupValidateFiles(parray *files, const char *root, bool size_onl
int
do_validate(pgBackupRange *range)
{
int i;
int i;
parray *backup_list;
catalog_lock();
@ -133,6 +133,7 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
for (i = 0; i < parray_num(files); i++)
{
struct stat st;
pgFile *file = (pgFile *) parray_get(files, i);
if (interrupted)
@ -168,7 +169,8 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
/* validate CRC too */
if (!size_only)
{
pg_crc32 crc;
pg_crc32 crc;
crc = pgFileGetCRC(file);
if (crc != file->crc)
{

70
xlog.c
View File

@ -26,29 +26,17 @@ typedef struct MemoryContextData *MemoryContext;
#define XLOG_PAGE_MAGIC_v82 0xD05E /* 8.2 */
#define XLOG_PAGE_MAGIC_v83 0xD062 /* 8.3 */
#define XLOG_PAGE_MAGIC_v84 0xD063 /* 8.4 */
#define XLOG_PAGE_MAGIC_v85 0xD063 /* 8.5 */
typedef struct XLogLongPageHeaderData_v81
{
XLogPageHeaderData std;
uint64 xlp_sysid;
uint32 xlp_seg_size;
} XLogLongPageHeaderData_v81, *XLogLongPageHeader_v81;
typedef struct XLogLongPageHeaderData_v82
{
XLogPageHeaderData std; /* standard header fields */
uint64 xlp_sysid; /* system identifier from pg_control */
uint32 xlp_seg_size; /* just as a cross-check */
uint32 xlp_xlog_blcksz; /* just as a cross-check */
} XLogLongPageHeaderData_v82, *XLogLongPageHeader_v82;
#define XLOG_PAGE_MAGIC_v85 0xD166 /* 8.5 */
/*
* XLogLongPageHeaderData is modified in 8.3, but the layout is compatible
* except xlp_xlog_blcksz.
*/
typedef union XLogPage
{
XLogPageHeaderData header;
XLogLongPageHeaderData_v81 long_v81; /* 8.1 - 8.2 */
XLogLongPageHeaderData_v82 long_v82; /* 8.3 - */
char data[XLOG_BLCKSZ];
XLogPageHeaderData header;
XLogLongPageHeaderData lheader;
char data[XLOG_BLCKSZ];
} XLogPage;
/*
@ -73,7 +61,9 @@ xlog_is_complete_wal(const pgFile *file, int server_version)
fclose(fp);
/* xlog_page_magic from server version */
if (server_version < 80100)
if (server_version < 80000)
return false; /* never happen */
else if (server_version < 80100)
xlog_page_magic = XLOG_PAGE_MAGIC_v80;
else if (server_version < 80200)
xlog_page_magic = XLOG_PAGE_MAGIC_v81;
@ -83,37 +73,29 @@ xlog_is_complete_wal(const pgFile *file, int server_version)
xlog_page_magic = XLOG_PAGE_MAGIC_v83;
else if (server_version < 80500)
xlog_page_magic = XLOG_PAGE_MAGIC_v84;
else
else if (server_version < 80600)
xlog_page_magic = XLOG_PAGE_MAGIC_v85;
else
return false; /* not supported */
/* check header */
if (page.header.xlp_magic != xlog_page_magic)
return false;
if ((page.header.xlp_info & ~XLP_ALL_FLAGS) != 0)
return false;
if (page.header.xlp_info & XLP_LONG_HEADER)
{
if (page.long_v81.xlp_seg_size != XLogSegSize)
return false;
if ((page.header.xlp_info & XLP_LONG_HEADER) == 0)
return false;
if (page.lheader.xlp_seg_size != XLogSegSize)
return false;
if (server_version >= 80300 && page.lheader.xlp_xlog_blcksz != XLOG_BLCKSZ)
return false;
/* compressed WAL (with lesslog) has 0 in lheader->xlp_xlog_blcksz. */
if (server_version >= 80300)
{
if (page.long_v82.xlp_xlog_blcksz == XLOG_BLCKSZ)
{
/* check size (actual file size, not backup file size) */
if (file->size != XLogSegSize)
return false;
}
else
{
if (page.long_v82.xlp_xlog_blcksz != 0)
return false;
}
}
else if (file->size != XLogSegSize)
return false;
}
/*
* check size (actual file size, not backup file size)
* TODO: Support pre-compressed xlog. They might have different file sizes.
*/
if (file->size != XLogSegSize)
return false;
return true;
}