1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2025-01-26 11:54:25 +02:00
pg_probackup/xlog.c
Michael Paquier 8aa6b84b98 Fix history file parsing when fetched from archive
History file format has changed from 9.2 to 9.3 to indicate the WAL record
when timeline branched off. In 9.2, the complete WAL file name was used
while in 9.3 the WAL record is used (like 1/4000090). pg_rman contains a
copy of a function of postgres core code to parse the history file that
was not anymore compatible, leading to errors related to timelines.
2013-12-10 17:27:51 +09:00

122 lines
3.2 KiB
C

/*-------------------------------------------------------------------------
*
* xlog.c: Parse WAL files.
*
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
*
*-------------------------------------------------------------------------
*/
#include "pg_rman.h"
#include <stdio.h>
#include <sys/types.h>
#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"
#define XLOG_PAGE_MAGIC_v80 0xD05C /* 8.0 */
#define XLOG_PAGE_MAGIC_v81 0xD05D /* 8.1 */
#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_v90 0xD064 /* 9.0 */
#define XLOG_PAGE_MAGIC_v91 0xD066 /* 9.1 */
#define XLOG_PAGE_MAGIC_v92 0xD071 /* 9.2 */
#define XLOG_PAGE_MAGIC_v93 0xD075 /* 9.2 */
/*
* XLogLongPageHeaderData is modified in 8.3, but the layout is compatible
* except xlp_xlog_blcksz.
*/
typedef union XLogPage
{
XLogPageHeaderData header;
XLogLongPageHeaderData lheader;
char data[XLOG_BLCKSZ];
} XLogPage;
/*
* Return whether the file is a WAL segment or not.
* based on ValidXLOGHeader() in src/backend/access/transam/xlog.c.
*/
bool
xlog_is_complete_wal(const pgFile *file, int server_version)
{
FILE *fp;
XLogPage page;
uint16 xlog_page_magic;
fp = fopen(file->path, "r");
if (!fp)
return false;
if (fread(&page, 1, sizeof(page), fp) != XLOG_BLCKSZ)
{
fclose(fp);
return false;
}
fclose(fp);
/* xlog_page_magic from server version */
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;
else if (server_version < 80300)
xlog_page_magic = XLOG_PAGE_MAGIC_v82;
else if (server_version < 80400)
xlog_page_magic = XLOG_PAGE_MAGIC_v83;
else if (server_version < 90000)
xlog_page_magic = XLOG_PAGE_MAGIC_v84;
else if (server_version < 90100)
xlog_page_magic = XLOG_PAGE_MAGIC_v90;
else if (server_version < 90200)
xlog_page_magic = XLOG_PAGE_MAGIC_v91;
else if (server_version < 90300)
xlog_page_magic = XLOG_PAGE_MAGIC_v92;
else if (server_version < 90400)
xlog_page_magic = XLOG_PAGE_MAGIC_v93;
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) == 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;
/*
* 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;
}
/*
* based on XLogFileName() in xlog_internal.h
*/
void
xlog_fname(char *fname, size_t len, TimeLineID tli, XLogRecPtr *lsn)
{
snprintf(fname, len, "%08X%08X%08X", tli,
(uint32) (*lsn / XLogSegSize),
(uint32) (*lsn % XLogSegSize));
}