PostgreSQL Source Code  git master
pg_rewind.h File Reference
#include "access/timeline.h"
#include "common/logging.h"
#include "datapagemap.h"
#include "libpq-fe.h"
#include "storage/block.h"
#include "storage/relfilenode.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.

Macros

#define pg_fatal(...)   do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0)
 

Functions

void extractPageMap (const char *datadir, XLogRecPtr startpoint, int tliIndex, XLogRecPtr endpoint, const char *restoreCommand)
 
void findLastCheckpoint (const char *datadir, XLogRecPtr searchptr, 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
 
TimeLineHistoryEntrytargetHistory
 
int targetNentries
 
uint64 fetch_size
 
uint64 fetch_done
 

Macro Definition Documentation

◆ pg_fatal

#define pg_fatal (   ...)    do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0)

Definition at line 37 of file pg_rewind.h.

Function Documentation

◆ extractPageMap()

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

Definition at line 63 of file parsexlog.c.

65 {
66  XLogRecord *record;
68  char *errormsg;
69  XLogPageReadPrivate private;
70 
71  private.tliIndex = tliIndex;
72  private.restoreCommand = restoreCommand;
74  XL_ROUTINE(.page_read = &SimpleXLogPageRead),
75  &private);
76  if (xlogreader == NULL)
77  pg_fatal("out of memory while allocating a WAL reading processor");
78 
79  XLogBeginRead(xlogreader, startpoint);
80  do
81  {
82  record = XLogReadRecord(xlogreader, &errormsg);
83 
84  if (record == NULL)
85  {
87 
88  if (errormsg)
89  pg_fatal("could not read WAL record at %X/%X: %s",
90  LSN_FORMAT_ARGS(errptr),
91  errormsg);
92  else
93  pg_fatal("could not read WAL record at %X/%X",
94  LSN_FORMAT_ARGS(errptr));
95  }
96 
98 
99  } while (xlogreader->EndRecPtr < endpoint);
100 
101  /*
102  * If 'endpoint' didn't point exactly at a record boundary, the caller
103  * messed up.
104  */
105  Assert(xlogreader->EndRecPtr == endpoint);
106 
108  if (xlogreadfd != -1)
109  {
110  close(xlogreadfd);
111  xlogreadfd = -1;
112  }
113 }
#define close(a)
Definition: win32.h:12
Assert(fmt[strlen(fmt) - 1] !='\n')
static int SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
Definition: parsexlog.c:250
static void extractPageInfo(XLogReaderState *record)
Definition: parsexlog.c:364
static int xlogreadfd
Definition: parsexlog.c:40
char * datadir
#define pg_fatal(...)
Definition: pg_rewind.h:37
uint32 WalSegSz
Definition: streamutil.c:34
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
static XLogReaderState * xlogreader
Definition: walsender.c:137
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition: xlogreader.c:271
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:142
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:78
void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)
Definition: xlogreader.c:243
#define XL_ROUTINE(...)
Definition: xlogreader.h:116

References Assert(), 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  searchptr,
int  tliIndex,
XLogRecPtr lastchkptrec,
TimeLineID lastchkpttli,
XLogRecPtr lastchkptredo,
const char *  restoreCommand 
)

Definition at line 164 of file parsexlog.c.

167 {
168  /* Walk backwards, starting from the given record */
169  XLogRecord *record;
170  XLogRecPtr searchptr;
172  char *errormsg;
173  XLogPageReadPrivate private;
174 
175  /*
176  * The given fork pointer points to the end of the last common record,
177  * which is not necessarily the beginning of the next record, if the
178  * previous record happens to end at a page boundary. Skip over the page
179  * header in that case to find the next record.
180  */
181  if (forkptr % XLOG_BLCKSZ == 0)
182  {
183  if (XLogSegmentOffset(forkptr, WalSegSz) == 0)
184  forkptr += SizeOfXLogLongPHD;
185  else
186  forkptr += SizeOfXLogShortPHD;
187  }
188 
189  private.tliIndex = tliIndex;
190  private.restoreCommand = restoreCommand;
192  XL_ROUTINE(.page_read = &SimpleXLogPageRead),
193  &private);
194  if (xlogreader == NULL)
195  pg_fatal("out of memory while allocating a WAL reading processor");
196 
197  searchptr = forkptr;
198  for (;;)
199  {
200  uint8 info;
201 
202  XLogBeginRead(xlogreader, searchptr);
203  record = XLogReadRecord(xlogreader, &errormsg);
204 
205  if (record == NULL)
206  {
207  if (errormsg)
208  pg_fatal("could not find previous WAL record at %X/%X: %s",
209  LSN_FORMAT_ARGS(searchptr),
210  errormsg);
211  else
212  pg_fatal("could not find previous WAL record at %X/%X",
213  LSN_FORMAT_ARGS(searchptr));
214  }
215 
216  /*
217  * Check if it is a checkpoint record. This checkpoint record needs to
218  * be the latest checkpoint before WAL forked and not the checkpoint
219  * where the primary has been stopped to be rewound.
220  */
222  if (searchptr < forkptr &&
223  XLogRecGetRmid(xlogreader) == RM_XLOG_ID &&
224  (info == XLOG_CHECKPOINT_SHUTDOWN ||
225  info == XLOG_CHECKPOINT_ONLINE))
226  {
227  CheckPoint checkPoint;
228 
229  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
230  *lastchkptrec = searchptr;
231  *lastchkpttli = checkPoint.ThisTimeLineID;
232  *lastchkptredo = checkPoint.redo;
233  break;
234  }
235 
236  /* Walk backwards to previous record. */
237  searchptr = record->xl_prev;
238  }
239 
241  if (xlogreadfd != -1)
242  {
243  close(xlogreadfd);
244  xlogreadfd = -1;
245  }
246 }
unsigned char uint8
Definition: c.h:439
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:68
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
XLogRecPtr redo
Definition: pg_control.h:37
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:315
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:316
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References close, datadir, LSN_FORMAT_ARGS, pg_fatal, CheckPoint::redo, SimpleXLogPageRead(), SizeOfXLogLongPHD, SizeOfXLogShortPHD, CheckPoint::ThisTimeLineID, WalSegSz, XLogRecord::xl_prev, XL_ROUTINE, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, XLogBeginRead(), xlogreader, XLogReaderAllocate(), XLogReaderFree(), xlogreadfd, XLogReadRecord(), XLogRecGetData, XLogRecGetInfo, XLogRecGetRmid, XLogSegmentOffset, and XLR_INFO_MASK.

Referenced by main().

◆ progress_report()

void progress_report ( bool  finished)

Definition at line 733 of file pg_rewind.c.

734 {
735  static pg_time_t last_progress_report = 0;
736  int percent;
737  char fetch_done_str[32];
738  char fetch_size_str[32];
739  pg_time_t now;
740 
741  if (!showprogress)
742  return;
743 
744  now = time(NULL);
745  if (now == last_progress_report && !finished)
746  return; /* Max once per second */
747 
749  percent = fetch_size ? (int) ((fetch_done) * 100 / fetch_size) : 0;
750 
751  /*
752  * Avoid overflowing past 100% or the full size. This may make the total
753  * size number change as we approach the end of the backup (the estimate
754  * will always be wrong if WAL is included), but that's better than having
755  * the done column be bigger than the total.
756  */
757  if (percent > 100)
758  percent = 100;
759  if (fetch_done > fetch_size)
761 
762  snprintf(fetch_done_str, sizeof(fetch_done_str), UINT64_FORMAT,
763  fetch_done / 1024);
764  snprintf(fetch_size_str, sizeof(fetch_size_str), UINT64_FORMAT,
765  fetch_size / 1024);
766 
767  fprintf(stderr, _("%*s/%s kB (%d%%) copied"),
768  (int) strlen(fetch_size_str), fetch_done_str, fetch_size_str,
769  percent);
770 
771  /*
772  * Stay on the same line if reporting to a terminal and we're not done
773  * yet.
774  */
775  fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
776 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1544
#define UINT64_FORMAT
Definition: c.h:484
#define _(x)
Definition: elog.c:89
static pg_time_t last_progress_report
Definition: pg_amcheck.c:144
uint64 fetch_done
Definition: pg_rewind.c:76
uint64 fetch_size
Definition: pg_rewind.c:75
bool showprogress
Definition: pg_rewind.c:65
int64 pg_time_t
Definition: pgtime.h:23
#define snprintf
Definition: port.h:225
#define fprintf
Definition: port.h:229

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 120 of file parsexlog.c.

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

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 29 of file timeline.c.

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

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

Referenced by getTimelineHistory().

Variable Documentation

◆ datadir_target

◆ do_sync

bool do_sync
extern

Definition at line 67 of file pg_rewind.c.

Referenced by main(), and perform_rewind().

◆ dry_run

◆ fetch_done

uint64 fetch_done
extern

Definition at line 76 of file pg_rewind.c.

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

◆ fetch_size

uint64 fetch_size
extern

Definition at line 75 of file pg_rewind.c.

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

◆ showprogress

bool showprogress
extern

Definition at line 65 of file pg_rewind.c.

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

◆ targetHistory

TimeLineHistoryEntry* targetHistory
extern

Definition at line 71 of file pg_rewind.c.

Referenced by findCommonAncestorTimeline(), main(), and SimpleXLogPageRead().

◆ targetNentries

int targetNentries
extern

◆ WalSegSz