PostgreSQL Source Code  git master
pg_rewind.h File Reference
#include "access/timeline.h"
#include "common/logging.h"
#include "common/file_utils.h"
#include "datapagemap.h"
#include "libpq-fe.h"
#include "storage/block.h"
#include "storage/relfilelocator.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  {
114  close(xlogreadfd);
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:254
static void extractPageInfo(XLogReaderState *record)
Definition: parsexlog.c:368
static int xlogreadfd
Definition: parsexlog.c:43
#define pg_fatal(...)
char * datadir
int WalSegSz
Definition: streamutil.c:34
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition: xlogreader.c:389
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:161
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:106
void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)
Definition: xlogreader.c:231
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188

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 
179  /*
180  * The given fork pointer points to the end of the last common record,
181  * which is not necessarily the beginning of the next record, if the
182  * previous record happens to end at a page boundary. Skip over the page
183  * header in that case to find the next record.
184  */
185  if (forkptr % XLOG_BLCKSZ == 0)
186  {
187  if (XLogSegmentOffset(forkptr, WalSegSz) == 0)
188  forkptr += SizeOfXLogLongPHD;
189  else
190  forkptr += SizeOfXLogShortPHD;
191  }
192 
193  private.tliIndex = tliIndex;
194  private.restoreCommand = restoreCommand;
196  XL_ROUTINE(.page_read = &SimpleXLogPageRead),
197  &private);
198  if (xlogreader == NULL)
199  pg_fatal("out of memory while allocating a WAL reading processor");
200 
201  searchptr = forkptr;
202  for (;;)
203  {
204  uint8 info;
205 
206  XLogBeginRead(xlogreader, searchptr);
207  record = XLogReadRecord(xlogreader, &errormsg);
208 
209  if (record == NULL)
210  {
211  if (errormsg)
212  pg_fatal("could not find previous WAL record at %X/%X: %s",
213  LSN_FORMAT_ARGS(searchptr),
214  errormsg);
215  else
216  pg_fatal("could not find previous WAL record at %X/%X",
217  LSN_FORMAT_ARGS(searchptr));
218  }
219 
220  /*
221  * Check if it is a checkpoint record. This checkpoint record needs to
222  * be the latest checkpoint before WAL forked and not the checkpoint
223  * where the primary has been stopped to be rewound.
224  */
226  if (searchptr < forkptr &&
227  XLogRecGetRmid(xlogreader) == RM_XLOG_ID &&
228  (info == XLOG_CHECKPOINT_SHUTDOWN ||
229  info == XLOG_CHECKPOINT_ONLINE))
230  {
231  CheckPoint checkPoint;
232 
233  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
234  *lastchkptrec = searchptr;
235  *lastchkpttli = checkPoint.ThisTimeLineID;
236  *lastchkptredo = checkPoint.redo;
237  break;
238  }
239 
240  /* Walk backwards to previous record. */
241  searchptr = record->xl_prev;
242  }
243 
245  if (xlogreadfd != -1)
246  {
247  close(xlogreadfd);
248  xlogreadfd = -1;
249  }
250 }
unsigned char uint8
Definition: c.h:491
#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:410
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:411
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#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 788 of file pg_rewind.c.

789 {
790  static pg_time_t last_progress_report = 0;
791  int percent;
792  char fetch_done_str[32];
793  char fetch_size_str[32];
794  pg_time_t now;
795 
796  if (!showprogress)
797  return;
798 
799  now = time(NULL);
800  if (now == last_progress_report && !finished)
801  return; /* Max once per second */
802 
804  percent = fetch_size ? (int) ((fetch_done) * 100 / fetch_size) : 0;
805 
806  /*
807  * Avoid overflowing past 100% or the full size. This may make the total
808  * size number change as we approach the end of the backup (the estimate
809  * will always be wrong if WAL is included), but that's better than having
810  * the done column be bigger than the total.
811  */
812  if (percent > 100)
813  percent = 100;
814  if (fetch_done > fetch_size)
816 
817  snprintf(fetch_done_str, sizeof(fetch_done_str), UINT64_FORMAT,
818  fetch_done / 1024);
819  snprintf(fetch_size_str, sizeof(fetch_size_str), UINT64_FORMAT,
820  fetch_size / 1024);
821 
822  fprintf(stderr, _("%*s/%s kB (%d%%) copied"),
823  (int) strlen(fetch_size_str), fetch_done_str, fetch_size_str,
824  percent);
825 
826  /*
827  * Stay on the same line if reporting to a terminal and we're not done
828  * yet.
829  */
830  fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
831 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1618
#define UINT64_FORMAT
Definition: c.h:536
#define _(x)
Definition: elog.c:90
static pg_time_t last_progress_report
Definition: pg_amcheck.c:146
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
#define snprintf
Definition: port.h:238
#define fprintf
Definition: port.h:242

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  {
157  close(xlogreadfd);
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;
31  TimeLineHistoryEntry *entry;
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 }
unsigned int uint32
Definition: c.h:493
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: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
uint32 TimeLineID
Definition: xlogdefs.h:59

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 getTimelineHistory(), main(), and SimpleXLogPageRead().

◆ WalSegSz