PostgreSQL Source Code git master
pg_rewind.h File Reference
#include "access/timeline.h"
#include "common/logging.h"
#include "common/file_utils.h"
Include dependency graph for pg_rewind.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void extractPageMap (const char *datadir, XLogRecPtr startpoint, int tliIndex, XLogRecPtr endpoint, const char *restoreCommand)
 
void findLastCheckpoint (const char *datadir, XLogRecPtr forkptr, int tliIndex, XLogRecPtr *lastchkptrec, TimeLineID *lastchkpttli, XLogRecPtr *lastchkptredo, const char *restoreCommand)
 
XLogRecPtr readOneRecord (const char *datadir, XLogRecPtr ptr, int tliIndex, const char *restoreCommand)
 
void progress_report (bool finished)
 
TimeLineHistoryEntryrewind_parseTimeLineHistory (char *buffer, TimeLineID targetTLI, int *nentries)
 

Variables

char * datadir_target
 
bool showprogress
 
bool dry_run
 
bool do_sync
 
int WalSegSz
 
DataDirSyncMethod sync_method
 
TimeLineHistoryEntrytargetHistory
 
int targetNentries
 
uint64 fetch_size
 
uint64 fetch_done
 

Function Documentation

◆ extractPageMap()

void extractPageMap ( const char *  datadir,
XLogRecPtr  startpoint,
int  tliIndex,
XLogRecPtr  endpoint,
const char *  restoreCommand 
)

Definition at line 66 of file parsexlog.c.

68{
69 XLogRecord *record;
71 char *errormsg;
72 XLogPageReadPrivate private;
73
74 private.tliIndex = tliIndex;
75 private.restoreCommand = restoreCommand;
77 XL_ROUTINE(.page_read = &SimpleXLogPageRead),
78 &private);
79 if (xlogreader == NULL)
80 pg_fatal("out of memory while allocating a WAL reading processor");
81
82 XLogBeginRead(xlogreader, startpoint);
83 do
84 {
85 record = XLogReadRecord(xlogreader, &errormsg);
86
87 if (record == NULL)
88 {
90
91 if (errormsg)
92 pg_fatal("could not read WAL record at %X/%X: %s",
93 LSN_FORMAT_ARGS(errptr),
94 errormsg);
95 else
96 pg_fatal("could not read WAL record at %X/%X",
97 LSN_FORMAT_ARGS(errptr));
98 }
99
101 } while (xlogreader->EndRecPtr < endpoint);
102
103 /*
104 * If 'endpoint' didn't point exactly at a record boundary, the caller
105 * messed up.
106 */
107 if (xlogreader->EndRecPtr != endpoint)
108 pg_fatal("end pointer %X/%X is not a valid end point; expected %X/%X",
110
112 if (xlogreadfd != -1)
113 {
115 xlogreadfd = -1;
116 }
117}
#define close(a)
Definition: win32.h:12
static int SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
Definition: parsexlog.c:275
static void extractPageInfo(XLogReaderState *record)
Definition: parsexlog.c:389
static int xlogreadfd
Definition: parsexlog.c:43
#define pg_fatal(...)
char * datadir
int WalSegSz
Definition: streamutil.c:32
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:107
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition: xlogreader.c:390
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:162
void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)
Definition: xlogreader.c:232
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:189

References close, datadir, XLogReaderState::EndRecPtr, extractPageInfo(), LSN_FORMAT_ARGS, pg_fatal, SimpleXLogPageRead(), XLogPageReadPrivate::tliIndex, WalSegSz, XL_ROUTINE, XLogBeginRead(), xlogreader, XLogReaderAllocate(), XLogReaderFree(), xlogreadfd, and XLogReadRecord().

Referenced by main().

◆ findLastCheckpoint()

void findLastCheckpoint ( const char *  datadir,
XLogRecPtr  forkptr,
int  tliIndex,
XLogRecPtr lastchkptrec,
TimeLineID lastchkpttli,
XLogRecPtr lastchkptredo,
const char *  restoreCommand 
)

Definition at line 168 of file parsexlog.c.

171{
172 /* Walk backwards, starting from the given record */
173 XLogRecord *record;
174 XLogRecPtr searchptr;
176 char *errormsg;
177 XLogPageReadPrivate private;
178 XLogSegNo current_segno = 0;
179 TimeLineID current_tli = 0;
180
181 /*
182 * The given fork pointer points to the end of the last common record,
183 * which is not necessarily the beginning of the next record, if the
184 * previous record happens to end at a page boundary. Skip over the page
185 * header in that case to find the next record.
186 */
187 if (forkptr % XLOG_BLCKSZ == 0)
188 {
189 if (XLogSegmentOffset(forkptr, WalSegSz) == 0)
190 forkptr += SizeOfXLogLongPHD;
191 else
192 forkptr += SizeOfXLogShortPHD;
193 }
194
195 private.tliIndex = tliIndex;
196 private.restoreCommand = restoreCommand;
198 XL_ROUTINE(.page_read = &SimpleXLogPageRead),
199 &private);
200 if (xlogreader == NULL)
201 pg_fatal("out of memory while allocating a WAL reading processor");
202
203 searchptr = forkptr;
204 for (;;)
205 {
206 uint8 info;
207
208 XLogBeginRead(xlogreader, searchptr);
209 record = XLogReadRecord(xlogreader, &errormsg);
210
211 if (record == NULL)
212 {
213 if (errormsg)
214 pg_fatal("could not find previous WAL record at %X/%X: %s",
215 LSN_FORMAT_ARGS(searchptr),
216 errormsg);
217 else
218 pg_fatal("could not find previous WAL record at %X/%X",
219 LSN_FORMAT_ARGS(searchptr));
220 }
221
222 /* Detect if a new WAL file has been opened */
223 if (xlogreader->seg.ws_tli != current_tli ||
224 xlogreader->seg.ws_segno != current_segno)
225 {
226 char xlogfname[MAXFNAMELEN];
227
228 snprintf(xlogfname, MAXFNAMELEN, XLOGDIR "/");
229
230 /* update current values */
231 current_tli = xlogreader->seg.ws_tli;
232 current_segno = xlogreader->seg.ws_segno;
233
234 XLogFileName(xlogfname + sizeof(XLOGDIR),
235 current_tli, current_segno, WalSegSz);
236
237 /* Track this filename as one to not remove */
238 keepwal_add_entry(xlogfname);
239 }
240
241 /*
242 * Check if it is a checkpoint record. This checkpoint record needs to
243 * be the latest checkpoint before WAL forked and not the checkpoint
244 * where the primary has been stopped to be rewound.
245 */
246 info = XLogRecGetInfo(xlogreader) & ~XLR_INFO_MASK;
247 if (searchptr < forkptr &&
248 XLogRecGetRmid(xlogreader) == RM_XLOG_ID &&
249 (info == XLOG_CHECKPOINT_SHUTDOWN ||
250 info == XLOG_CHECKPOINT_ONLINE))
251 {
252 CheckPoint checkPoint;
253
254 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
255 *lastchkptrec = searchptr;
256 *lastchkpttli = checkPoint.ThisTimeLineID;
257 *lastchkptredo = checkPoint.redo;
258 break;
259 }
260
261 /* Walk backwards to previous record. */
262 searchptr = record->xl_prev;
263 }
264
266 if (xlogreadfd != -1)
267 {
269 xlogreadfd = -1;
270 }
271}
uint8_t uint8
Definition: c.h:486
void keepwal_add_entry(const char *path)
Definition: filemap.c:250
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:68
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:69
#define snprintf
Definition: port.h:239
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
XLogRecPtr redo
Definition: pg_control.h:37
XLogSegNo ws_segno
Definition: xlogreader.h:48
TimeLineID ws_tli
Definition: xlogreader.h:49
WALOpenSegment seg
Definition: xlogreader.h:272
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
#define MAXFNAMELEN
#define XLOGDIR
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint32 TimeLineID
Definition: xlogdefs.h:59
uint64 XLogSegNo
Definition: xlogdefs.h:48
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:411
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415

References close, datadir, keepwal_add_entry(), LSN_FORMAT_ARGS, MAXFNAMELEN, pg_fatal, CheckPoint::redo, XLogReaderState::seg, SimpleXLogPageRead(), SizeOfXLogLongPHD, SizeOfXLogShortPHD, snprintf, CheckPoint::ThisTimeLineID, WalSegSz, WALOpenSegment::ws_segno, WALOpenSegment::ws_tli, XLogRecord::xl_prev, XL_ROUTINE, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, XLogBeginRead(), XLOGDIR, XLogFileName(), xlogreader, XLogReaderAllocate(), XLogReaderFree(), xlogreadfd, XLogReadRecord(), XLogRecGetData, XLogRecGetInfo, XLogRecGetRmid, and XLogSegmentOffset.

Referenced by main().

◆ progress_report()

void progress_report ( bool  finished)

Definition at line 791 of file pg_rewind.c.

792{
794 int percent;
795 char fetch_done_str[32];
796 char fetch_size_str[32];
798
799 if (!showprogress)
800 return;
801
802 now = time(NULL);
803 if (now == last_progress_report && !finished)
804 return; /* Max once per second */
805
807 percent = fetch_size ? (int) ((fetch_done) * 100 / fetch_size) : 0;
808
809 /*
810 * Avoid overflowing past 100% or the full size. This may make the total
811 * size number change as we approach the end of the backup (the estimate
812 * will always be wrong if WAL is included), but that's better than having
813 * the done column be bigger than the total.
814 */
815 if (percent > 100)
816 percent = 100;
819
820 snprintf(fetch_done_str, sizeof(fetch_done_str), UINT64_FORMAT,
821 fetch_done / 1024);
822 snprintf(fetch_size_str, sizeof(fetch_size_str), UINT64_FORMAT,
823 fetch_size / 1024);
824
825 fprintf(stderr, _("%*s/%s kB (%d%%) copied"),
826 (int) strlen(fetch_size_str), fetch_done_str, fetch_size_str,
827 percent);
828
829 /*
830 * Stay on the same line if reporting to a terminal and we're not done
831 * yet.
832 */
833 fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
834}
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
#define UINT64_FORMAT
Definition: c.h:507
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
#define _(x)
Definition: elog.c:90
static pg_time_t last_progress_report
Definition: pg_amcheck.c:147
uint64 fetch_done
Definition: pg_rewind.c:86
uint64 fetch_size
Definition: pg_rewind.c:85
bool showprogress
Definition: pg_rewind.c:74
int64 pg_time_t
Definition: pgtime.h:23

References _, fetch_done, fetch_size, fprintf, last_progress_report, now(), showprogress, snprintf, and UINT64_FORMAT.

Referenced by perform_rewind().

◆ readOneRecord()

XLogRecPtr readOneRecord ( const char *  datadir,
XLogRecPtr  ptr,
int  tliIndex,
const char *  restoreCommand 
)

Definition at line 124 of file parsexlog.c.

126{
127 XLogRecord *record;
129 char *errormsg;
130 XLogPageReadPrivate private;
131 XLogRecPtr endptr;
132
133 private.tliIndex = tliIndex;
134 private.restoreCommand = restoreCommand;
136 XL_ROUTINE(.page_read = &SimpleXLogPageRead),
137 &private);
138 if (xlogreader == NULL)
139 pg_fatal("out of memory while allocating a WAL reading processor");
140
142 record = XLogReadRecord(xlogreader, &errormsg);
143 if (record == NULL)
144 {
145 if (errormsg)
146 pg_fatal("could not read WAL record at %X/%X: %s",
147 LSN_FORMAT_ARGS(ptr), errormsg);
148 else
149 pg_fatal("could not read WAL record at %X/%X",
150 LSN_FORMAT_ARGS(ptr));
151 }
152 endptr = xlogreader->EndRecPtr;
153
155 if (xlogreadfd != -1)
156 {
158 xlogreadfd = -1;
159 }
160
161 return endptr;
162}

References close, datadir, XLogReaderState::EndRecPtr, LSN_FORMAT_ARGS, pg_fatal, SimpleXLogPageRead(), XLogPageReadPrivate::tliIndex, WalSegSz, XL_ROUTINE, XLogBeginRead(), xlogreader, XLogReaderAllocate(), XLogReaderFree(), xlogreadfd, and XLogReadRecord().

Referenced by main().

◆ rewind_parseTimeLineHistory()

TimeLineHistoryEntry * rewind_parseTimeLineHistory ( char *  buffer,
TimeLineID  targetTLI,
int *  nentries 
)

Definition at line 28 of file timeline.c.

29{
30 char *fline;
32 TimeLineHistoryEntry *entries = NULL;
33 int nlines = 0;
34 TimeLineID lasttli = 0;
35 XLogRecPtr prevend;
36 char *bufptr;
37 bool lastline = false;
38
39 /*
40 * Parse the file...
41 */
42 prevend = InvalidXLogRecPtr;
43 bufptr = buffer;
44 while (!lastline)
45 {
46 char *ptr;
47 TimeLineID tli;
48 uint32 switchpoint_hi;
49 uint32 switchpoint_lo;
50 int nfields;
51
52 fline = bufptr;
53 while (*bufptr && *bufptr != '\n')
54 bufptr++;
55 if (!(*bufptr))
56 lastline = true;
57 else
58 *bufptr++ = '\0';
59
60 /* skip leading whitespace and check for # comment */
61 for (ptr = fline; *ptr; ptr++)
62 {
63 if (!isspace((unsigned char) *ptr))
64 break;
65 }
66 if (*ptr == '\0' || *ptr == '#')
67 continue;
68
69 nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
70
71 if (nfields < 1)
72 {
73 /* expect a numeric timeline ID as first field of line */
74 pg_log_error("syntax error in history file: %s", fline);
75 pg_log_error_detail("Expected a numeric timeline ID.");
76 exit(1);
77 }
78 if (nfields != 3)
79 {
80 pg_log_error("syntax error in history file: %s", fline);
81 pg_log_error_detail("Expected a write-ahead log switchpoint location.");
82 exit(1);
83 }
84 if (entries && tli <= lasttli)
85 {
86 pg_log_error("invalid data in history file: %s", fline);
87 pg_log_error_detail("Timeline IDs must be in increasing sequence.");
88 exit(1);
89 }
90
91 lasttli = tli;
92
93 nlines++;
94 entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry));
95
96 entry = &entries[nlines - 1];
97 entry->tli = tli;
98 entry->begin = prevend;
99 entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
100 prevend = entry->end;
101
102 /* we ignore the remainder of each line */
103 }
104
105 if (entries && targetTLI <= lasttli)
106 {
107 pg_log_error("invalid data in history file");
108 pg_log_error_detail("Timeline IDs must be less than child timeline's ID.");
109 exit(1);
110 }
111
112 /*
113 * Create one more entry for the "tip" of the timeline, which has no entry
114 * in the history file.
115 */
116 nlines++;
117 if (entries)
118 entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry));
119 else
120 entries = pg_malloc(1 * sizeof(TimeLineHistoryEntry));
121
122 entry = &entries[nlines - 1];
123 entry->tli = targetTLI;
124 entry->begin = prevend;
125 entry->end = InvalidXLogRecPtr;
126
127 *nentries = nlines;
128 return entries;
129}
uint64_t uint64
Definition: c.h:489
uint32_t uint32
Definition: c.h:488
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
exit(1)
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_detail(...)
Definition: logging.h:109
XLogRecPtr begin
Definition: timeline.h:28
TimeLineID tli
Definition: timeline.h:27
XLogRecPtr end
Definition: timeline.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

References TimeLineHistoryEntry::begin, TimeLineHistoryEntry::end, exit(), InvalidXLogRecPtr, pg_log_error, pg_log_error_detail, pg_malloc(), pg_realloc(), and TimeLineHistoryEntry::tli.

Referenced by getTimelineHistory().

Variable Documentation

◆ datadir_target

◆ do_sync

bool do_sync
extern

Definition at line 76 of file pg_rewind.c.

Referenced by main(), and perform_rewind().

◆ dry_run

bool dry_run
extern

Definition at line 75 of file pg_rewind.c.

Referenced by ensureCleanShutdown(), main(), and perform_rewind().

◆ fetch_done

uint64 fetch_done
extern

Definition at line 86 of file pg_rewind.c.

Referenced by main(), progress_report(), and write_target_range().

◆ fetch_size

uint64 fetch_size
extern

Definition at line 85 of file pg_rewind.c.

Referenced by main(), postgresAcquireSampleRowsFunc(), and progress_report().

◆ showprogress

bool showprogress
extern

Definition at line 74 of file pg_rewind.c.

Referenced by main(), perform_rewind(), and progress_report().

◆ sync_method

DataDirSyncMethod sync_method
extern

Definition at line 78 of file pg_rewind.c.

Referenced by main().

◆ targetHistory

TimeLineHistoryEntry* targetHistory
extern

Definition at line 81 of file pg_rewind.c.

Referenced by main(), and SimpleXLogPageRead().

◆ targetNentries

int targetNentries
extern

Definition at line 82 of file pg_rewind.c.

Referenced by main(), and SimpleXLogPageRead().

◆ WalSegSz