Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)