Skip to content

Commit efd552e

Browse files
committed
Check WALs in validate command. Also support 64bit XID from PGPRO_EE. issue #5
1 parent ed8fbca commit efd552e

File tree

7 files changed

+164
-42
lines changed

7 files changed

+164
-42
lines changed

backup.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static void pg_start_backup(const char *label, bool smooth, pgBackup *backup);
6464
static void pg_stop_backup(pgBackup *backup);
6565
static bool pg_is_standby(void);
6666
static void get_lsn(PGconn *conn, PGresult *res, XLogRecPtr *lsn, bool stop_backup);
67-
static void get_xid(PGresult *res, uint32 *xid);
67+
static void get_xid(PGresult *res, TransactionId *xid);
6868
static void pg_ptrack_clear(void);
6969
static bool pg_ptrack_support(void);
7070
static bool pg_ptrack_enable(void);
@@ -1042,14 +1042,14 @@ get_lsn(PGconn *conn, PGresult *res, XLogRecPtr *lsn, bool stop_backup)
10421042
* Get XID from result of txid_current() after pg_stop_backup().
10431043
*/
10441044
static void
1045-
get_xid(PGresult *res, uint32 *xid)
1045+
get_xid(PGresult *res, TransactionId *xid)
10461046
{
10471047
if (res == NULL || PQntuples(res) != 1 || PQnfields(res) != 1)
10481048
elog(ERROR,
10491049
"result of txid_current() is invalid: %s",
10501050
PQerrorMessage(connection));
10511051

1052-
if (sscanf(PQgetvalue(res, 0, 0), "%u", xid) != 1)
1052+
if (sscanf(PQgetvalue(res, 0, 0), XID_FMT, xid) != 1)
10531053
{
10541054
elog(ERROR,
10551055
"result of txid_current() is invalid: %s",

catalog.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -331,21 +331,21 @@ catalog_read_ini(const char *path)
331331

332332
pgut_option options[] =
333333
{
334-
{ 's', 0, "backup-mode" , NULL, SOURCE_ENV },
335-
{ 'u', 0, "timelineid" , NULL, SOURCE_ENV },
336-
{ 's', 0, "start-lsn" , NULL, SOURCE_ENV },
337-
{ 's', 0, "stop-lsn" , NULL, SOURCE_ENV },
338-
{ 't', 0, "start-time" , NULL, SOURCE_ENV },
339-
{ 't', 0, "end-time" , NULL, SOURCE_ENV },
340-
{ 'u', 0, "recovery-xid" , NULL, SOURCE_ENV },
341-
{ 't', 0, "recovery-time" , NULL, SOURCE_ENV },
342-
{ 'I', 0, "data-bytes" , NULL, SOURCE_ENV },
343-
{ 'u', 0, "block-size" , NULL, SOURCE_ENV },
344-
{ 'u', 0, "xlog-block-size" , NULL, SOURCE_ENV },
345-
{ 'u', 0, "checksum_version" , NULL, SOURCE_ENV },
346-
{ 'u', 0, "stream" , NULL, SOURCE_ENV },
347-
{ 's', 0, "status" , NULL, SOURCE_ENV },
348-
{ 0 }
334+
{'s', 0, "backup-mode", NULL, SOURCE_ENV},
335+
{'u', 0, "timelineid", NULL, SOURCE_ENV},
336+
{'s', 0, "start-lsn", NULL, SOURCE_ENV},
337+
{'s', 0, "stop-lsn", NULL, SOURCE_ENV},
338+
{'t', 0, "start-time", NULL, SOURCE_ENV},
339+
{'t', 0, "end-time", NULL, SOURCE_ENV},
340+
{'U', 0, "recovery-xid", NULL, SOURCE_ENV},
341+
{'t', 0, "recovery-time", NULL, SOURCE_ENV},
342+
{'I', 0, "data-bytes", NULL, SOURCE_ENV},
343+
{'u', 0, "block-size", NULL, SOURCE_ENV},
344+
{'u', 0, "xlog-block-size", NULL, SOURCE_ENV},
345+
{'u', 0, "checksum_version", NULL, SOURCE_ENV},
346+
{'u', 0, "stream", NULL, SOURCE_ENV},
347+
{'s', 0, "status", NULL, SOURCE_ENV},
348+
{0}
349349
};
350350

351351
if (access(path, F_OK) != 0)

parsexlog.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "commands/dbcommands_xlog.h"
1919
#include "catalog/storage_xlog.h"
20+
#include "access/transam.h"
2021

2122
/*
2223
* RmgrNames is an array of resource manager names, to make error messages
@@ -100,6 +101,85 @@ extractPageMap(const char *archivedir, XLogRecPtr startpoint, TimeLineID tli,
100101
}
101102
}
102103

104+
void
105+
validate_wal(pgBackup *backup,
106+
const char *archivedir,
107+
XLogRecPtr startpoint,
108+
time_t target_time,
109+
TransactionId recovery_target_xid,
110+
TimeLineID tli)
111+
{
112+
XLogRecord *record;
113+
XLogReaderState *xlogreader;
114+
char *errormsg;
115+
XLogPageReadPrivate private;
116+
TransactionId last_xid = InvalidTransactionId;
117+
TimestampTz last_time = 0;
118+
char timestamp[100];
119+
120+
private.archivedir = archivedir;
121+
private.tli = tli;
122+
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
123+
if (xlogreader == NULL)
124+
elog(ERROR, "out of memory");
125+
126+
while (true)
127+
{
128+
record = XLogReadRecord(xlogreader, startpoint, &errormsg);
129+
bool timestamp_record;
130+
if (record == NULL)
131+
{
132+
XLogRecPtr errptr;
133+
134+
errptr = startpoint ? startpoint : xlogreader->EndRecPtr;
135+
if (recovery_target_xid == InvalidTransactionId && target_time == 0)
136+
{
137+
break;
138+
}
139+
140+
if (errormsg)
141+
elog(ERROR, "stop check WALs because could not read WAL record at %X/%X: %s\nend time:%s end xid:" XID_FMT,
142+
(uint32) (errptr >> 32), (uint32) (errptr),
143+
errormsg,
144+
timestamp,
145+
last_xid);
146+
else
147+
elog(ERROR, "could not read WAL record at %X/%X\nend time:%s end xid:" XID_FMT,
148+
(uint32) (errptr >> 32),
149+
(uint32) (errptr),
150+
timestamp,
151+
last_xid);
152+
}
153+
154+
timestamp_record = getRecordTimestamp(xlogreader, &last_time);
155+
last_xid = XLogRecGetXid(xlogreader);
156+
if (recovery_target_xid != InvalidTransactionId && recovery_target_xid == last_xid)
157+
break;
158+
159+
if (target_time != 0 && timestamp_record && timestamptz_to_time_t(last_time) >= target_time)
160+
break;
161+
162+
startpoint = InvalidXLogRecPtr; /* continue reading at next record */
163+
}
164+
165+
if (last_time > 0)
166+
time2iso(timestamp, lengthof(timestamp), timestamptz_to_time_t(last_time));
167+
else
168+
time2iso(timestamp, lengthof(timestamp), backup->recovery_time);
169+
if (last_xid == InvalidTransactionId)
170+
last_xid = backup->recovery_xid;
171+
172+
elog(INFO, "Validate WAL stoped on %s time and xid:" XID_FMT, timestamp, last_xid);
173+
174+
/* clean */
175+
XLogReaderFree(xlogreader);
176+
if (xlogreadfd != -1)
177+
{
178+
close(xlogreadfd);
179+
xlogreadfd = -1;
180+
}
181+
}
182+
103183
/* XLogreader callback function, to read a WAL page */
104184
static int
105185
SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
@@ -138,7 +218,7 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
138218

139219
if (xlogreadfd < 0)
140220
{
141-
elog(WARNING, "could not open WAL segment \"%s\": %s",
221+
elog(INFO, "could not open WAL segment \"%s\": %s",
142222
xlogfpath, strerror(errno));
143223
return -1;
144224
}

pg_probackup.h

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
#define DIR_PERMISSION (0700)
4646
#define FILE_PERMISSION (0600)
4747

48+
#ifndef PGPRO_EE
49+
#define XID_FMT "%u"
50+
#endif
51+
4852
/* backup mode file */
4953
typedef struct pgFile
5054
{
@@ -107,33 +111,33 @@ typedef enum BackupMode
107111
typedef struct pgBackup
108112
{
109113
/* Backup Level */
110-
BackupMode backup_mode;
114+
BackupMode backup_mode;
111115

112116
/* Status - one of BACKUP_STATUS_xxx */
113117
BackupStatus status;
114118

115119
/* Timestamp, etc. */
116-
TimeLineID tli;
117-
XLogRecPtr start_lsn;
118-
XLogRecPtr stop_lsn;
119-
time_t start_time;
120-
time_t end_time;
121-
time_t recovery_time;
122-
uint32 recovery_xid;
120+
TimeLineID tli;
121+
XLogRecPtr start_lsn;
122+
XLogRecPtr stop_lsn;
123+
time_t start_time;
124+
time_t end_time;
125+
time_t recovery_time;
126+
TransactionId recovery_xid;
123127

124128
/* Different sizes (-1 means nothing was backed up) */
125129
/*
126130
* Amount of raw data. For a full backup, this is the total amount of
127131
* data while for a differential backup this is just the difference
128132
* of data taken.
129133
*/
130-
int64 data_bytes;
134+
int64 data_bytes;
131135

132136
/* data/wal block size for compatibility check */
133-
uint32 block_size;
134-
uint32 wal_block_size;
135-
uint32 checksum_version;
136-
bool stream;
137+
uint32 block_size;
138+
uint32 wal_block_size;
139+
uint32 checksum_version;
140+
bool stream;
137141
} pgBackup;
138142

139143
typedef struct pgBackupOption
@@ -156,11 +160,11 @@ typedef struct pgTimeLine
156160

157161
typedef struct pgRecoveryTarget
158162
{
159-
bool time_specified;
160-
time_t recovery_target_time;
161-
bool xid_specified;
162-
unsigned int recovery_target_xid;
163-
bool recovery_target_inclusive;
163+
bool time_specified;
164+
time_t recovery_target_time;
165+
bool xid_specified;
166+
TransactionId recovery_target_xid;
167+
bool recovery_target_inclusive;
164168
} pgRecoveryTarget;
165169

166170
typedef union DataPage
@@ -313,8 +317,16 @@ extern bool copy_file(const char *from_root, const char *to_root,
313317
extern bool calc_file(pgFile *file);
314318

315319
/* parsexlog.c */
316-
extern void extractPageMap(const char *datadir, XLogRecPtr startpoint,
317-
TimeLineID tli, XLogRecPtr endpoint);
320+
extern void extractPageMap(const char *datadir,
321+
XLogRecPtr startpoint,
322+
TimeLineID tli,
323+
XLogRecPtr endpoint);
324+
extern void validate_wal(pgBackup *backup,
325+
const char *archivedir,
326+
XLogRecPtr startpoint,
327+
time_t target_time,
328+
TransactionId recovery_target_xid,
329+
TimeLineID tli);
318330

319331
/* in util.c */
320332
extern TimeLineID get_current_timeline(bool safe);
@@ -328,6 +340,7 @@ extern uint32 get_data_checksum_version(bool safe);
328340
extern char *base36enc(long unsigned int value);
329341
extern long unsigned int base36dec(const char *text);
330342
extern uint64 get_system_identifier(bool safe);
343+
extern pg_time_t timestamptz_to_time_t(TimestampTz t);
331344

332345
/* in status.c */
333346
extern bool is_pg_running(void);

restore.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,9 +777,9 @@ checkIfCreateRecoveryConf(const char *target_time,
777777
const char *target_xid,
778778
const char *target_inclusive)
779779
{
780-
time_t dummy_time;
781-
unsigned int dummy_xid;
782-
bool dummy_bool;
780+
time_t dummy_time;
781+
TransactionId dummy_xid;
782+
bool dummy_bool;
783783
pgRecoveryTarget *rt;
784784

785785
/* Initialize pgRecoveryTarget */
@@ -801,7 +801,11 @@ checkIfCreateRecoveryConf(const char *target_time,
801801
if (target_xid)
802802
{
803803
rt->xid_specified = true;
804+
#ifdef PGPRO_EE
805+
if (parse_uint64(target_xid, &dummy_xid))
806+
#else
804807
if (parse_uint32(target_xid, &dummy_xid))
808+
#endif
805809
rt->recovery_target_xid = dummy_xid;
806810
else
807811
elog(ERROR, "cannot create recovery.conf with %s", target_xid);

util.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,22 @@ time2iso(char *buf, size_t len, time_t time)
168168
strftime(buf, len, "%Y-%m-%d %H:%M:%S", tm);
169169
}
170170

171+
/* copied from timestamp.c */
172+
pg_time_t
173+
timestamptz_to_time_t(TimestampTz t)
174+
{
175+
pg_time_t result;
176+
177+
#ifdef HAVE_INT64_TIMESTAMP
178+
result = (pg_time_t) (t / USECS_PER_SEC +
179+
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
180+
#else
181+
result = (pg_time_t) (t +
182+
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
183+
#endif
184+
return result;
185+
}
186+
171187
const char *
172188
status2str(BackupStatus status)
173189
{

validate.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ int do_validate(time_t backup_id,
193193
}
194194

195195
/* and now we must check WALs */
196+
{
197+
pgBackup *backup = (pgBackup *) parray_get(backups, last_restored_index);
198+
validate_wal(backup,
199+
arclog_path,
200+
backup->start_lsn,
201+
rt->recovery_target_time,
202+
rt->recovery_target_xid,
203+
target_tli);
204+
}
196205

197206
/* release catalog lock */
198207
catalog_unlock();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy