PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
timeline.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include <unistd.h>
#include "access/timeline.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogdefs.h"
#include "storage/fd.h"
Include dependency graph for timeline.c:

Go to the source code of this file.

Functions

void restoreTimeLineHistoryFiles (TimeLineID begin, TimeLineID end)
 
ListreadTimeLineHistory (TimeLineID targetTLI)
 
bool existsTimeLineHistory (TimeLineID probeTLI)
 
TimeLineID findNewestTimeLine (TimeLineID startTLI)
 
void writeTimeLineHistory (TimeLineID newTLI, TimeLineID parentTLI, XLogRecPtr switchpoint, char *reason)
 
void writeTimeLineHistoryFile (TimeLineID tli, char *content, int size)
 
bool tliInHistory (TimeLineID tli, List *expectedTLEs)
 
TimeLineID tliOfPointInHistory (XLogRecPtr ptr, List *history)
 
XLogRecPtr tliSwitchPoint (TimeLineID tli, List *history, TimeLineID *nextTLI)
 

Function Documentation

bool existsTimeLineHistory ( TimeLineID  probeTLI)

Definition at line 206 of file timeline.c.

References AllocateFile(), ArchiveRecoveryRequested, ereport, errcode_for_file_access(), errmsg(), FATAL, fd(), FreeFile(), MAXFNAMELEN, MAXPGPATH, NULL, RestoreArchivedFile(), TLHistoryFileName, and TLHistoryFilePath.

Referenced by findNewestTimeLine(), readRecoveryCommandFile(), and WalRcvFetchTimeLineHistoryFiles().

207 {
208  char path[MAXPGPATH];
209  char histfname[MAXFNAMELEN];
210  FILE *fd;
211 
212  /* Timeline 1 does not have a history file, so no need to check */
213  if (probeTLI == 1)
214  return false;
215 
217  {
218  TLHistoryFileName(histfname, probeTLI);
219  RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
220  }
221  else
222  TLHistoryFilePath(path, probeTLI);
223 
224  fd = AllocateFile(path, "r");
225  if (fd != NULL)
226  {
227  FreeFile(fd);
228  return true;
229  }
230  else
231  {
232  if (errno != ENOENT)
233  ereport(FATAL,
235  errmsg("could not open file \"%s\": %m", path)));
236  return false;
237  }
238 }
bool ArchiveRecoveryRequested
Definition: xlog.c:245
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition: xlogarchive.c:51
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define FATAL
Definition: elog.h:52
#define MAXPGPATH
#define TLHistoryFileName(fname, tli)
int errcode_for_file_access(void)
Definition: elog.c:598
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2043
#define ereport(elevel, rest)
Definition: elog.h:122
#define MAXFNAMELEN
#define NULL
Definition: c.h:226
int FreeFile(FILE *file)
Definition: fd.c:2226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define TLHistoryFilePath(path, tli)
TimeLineID findNewestTimeLine ( TimeLineID  startTLI)

Definition at line 248 of file timeline.c.

References existsTimeLineHistory().

Referenced by readRecoveryCommandFile(), rescanLatestTimeLine(), and StartupXLOG().

249 {
250  TimeLineID newestTLI;
251  TimeLineID probeTLI;
252 
253  /*
254  * The algorithm is just to probe for the existence of timeline history
255  * files. XXX is it useful to allow gaps in the sequence?
256  */
257  newestTLI = startTLI;
258 
259  for (probeTLI = startTLI + 1;; probeTLI++)
260  {
261  if (existsTimeLineHistory(probeTLI))
262  {
263  newestTLI = probeTLI; /* probeTLI exists */
264  }
265  else
266  {
267  /* doesn't exist, assume we're done */
268  break;
269  }
270  }
271 
272  return newestTLI;
273 }
uint32 TimeLineID
Definition: xlogdefs.h:45
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition: timeline.c:206
List* readTimeLineHistory ( TimeLineID  targetTLI)

Definition at line 74 of file timeline.c.

References AllocateFile(), ArchiveRecoveryRequested, TimeLineHistoryEntry::begin, TimeLineHistoryEntry::end, ereport, errcode_for_file_access(), errhint(), errmsg(), FATAL, fd(), FreeFile(), InvalidXLogRecPtr, KeepFileRestoredFromArchive(), lcons(), list_make1, MAXFNAMELEN, MAXPGPATH, NIL, NULL, palloc(), RestoreArchivedFile(), TLHistoryFileName, TLHistoryFilePath, and TimeLineHistoryEntry::tli.

Referenced by rescanLatestTimeLine(), StartReplication(), WaitForWALToBecomeAvailable(), XLogFileReadAnyTLI(), and XLogSendPhysical().

75 {
76  List *result;
77  char path[MAXPGPATH];
78  char histfname[MAXFNAMELEN];
79  char fline[MAXPGPATH];
80  FILE *fd;
81  TimeLineHistoryEntry *entry;
82  TimeLineID lasttli = 0;
83  XLogRecPtr prevend;
84  bool fromArchive = false;
85 
86  /* Timeline 1 does not have a history file, so no need to check */
87  if (targetTLI == 1)
88  {
90  entry->tli = targetTLI;
91  entry->begin = entry->end = InvalidXLogRecPtr;
92  return list_make1(entry);
93  }
94 
96  {
97  TLHistoryFileName(histfname, targetTLI);
98  fromArchive =
99  RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
100  }
101  else
102  TLHistoryFilePath(path, targetTLI);
103 
104  fd = AllocateFile(path, "r");
105  if (fd == NULL)
106  {
107  if (errno != ENOENT)
108  ereport(FATAL,
110  errmsg("could not open file \"%s\": %m", path)));
111  /* Not there, so assume no parents */
112  entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
113  entry->tli = targetTLI;
114  entry->begin = entry->end = InvalidXLogRecPtr;
115  return list_make1(entry);
116  }
117 
118  result = NIL;
119 
120  /*
121  * Parse the file...
122  */
123  prevend = InvalidXLogRecPtr;
124  while (fgets(fline, sizeof(fline), fd) != NULL)
125  {
126  /* skip leading whitespace and check for # comment */
127  char *ptr;
128  TimeLineID tli;
129  uint32 switchpoint_hi;
130  uint32 switchpoint_lo;
131  int nfields;
132 
133  for (ptr = fline; *ptr; ptr++)
134  {
135  if (!isspace((unsigned char) *ptr))
136  break;
137  }
138  if (*ptr == '\0' || *ptr == '#')
139  continue;
140 
141  nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
142 
143  if (nfields < 1)
144  {
145  /* expect a numeric timeline ID as first field of line */
146  ereport(FATAL,
147  (errmsg("syntax error in history file: %s", fline),
148  errhint("Expected a numeric timeline ID.")));
149  }
150  if (nfields != 3)
151  ereport(FATAL,
152  (errmsg("syntax error in history file: %s", fline),
153  errhint("Expected a transaction log switchpoint location.")));
154 
155  if (result && tli <= lasttli)
156  ereport(FATAL,
157  (errmsg("invalid data in history file: %s", fline),
158  errhint("Timeline IDs must be in increasing sequence.")));
159 
160  lasttli = tli;
161 
162  entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
163  entry->tli = tli;
164  entry->begin = prevend;
165  entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
166  prevend = entry->end;
167 
168  /* Build list with newest item first */
169  result = lcons(entry, result);
170 
171  /* we ignore the remainder of each line */
172  }
173 
174  FreeFile(fd);
175 
176  if (result && targetTLI <= lasttli)
177  ereport(FATAL,
178  (errmsg("invalid data in history file \"%s\"", path),
179  errhint("Timeline IDs must be less than child timeline's ID.")));
180 
181  /*
182  * Create one more entry for the "tip" of the timeline, which has no entry
183  * in the history file.
184  */
185  entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
186  entry->tli = targetTLI;
187  entry->begin = prevend;
188  entry->end = InvalidXLogRecPtr;
189 
190  result = lcons(entry, result);
191 
192  /*
193  * If the history file was fetched from archive, save it in pg_wal for
194  * future reference.
195  */
196  if (fromArchive)
197  KeepFileRestoredFromArchive(path, histfname);
198 
199  return result;
200 }
bool ArchiveRecoveryRequested
Definition: xlog.c:245
#define NIL
Definition: pg_list.h:69
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
int errhint(const char *fmt,...)
Definition: elog.c:987
uint32 TimeLineID
Definition: xlogdefs.h:45
void KeepFileRestoredFromArchive(char *path, char *xlogfname)
Definition: xlogarchive.c:426
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition: xlogarchive.c:51
TimeLineID tli
Definition: timeline.h:27
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define list_make1(x1)
Definition: pg_list.h:133
#define FATAL
Definition: elog.h:52
#define MAXPGPATH
#define TLHistoryFileName(fname, tli)
int errcode_for_file_access(void)
Definition: elog.c:598
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2043
unsigned int uint32
Definition: c.h:265
#define ereport(elevel, rest)
Definition: elog.h:122
#define MAXFNAMELEN
List * lcons(void *datum, List *list)
Definition: list.c:259
#define NULL
Definition: c.h:226
XLogRecPtr end
Definition: timeline.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
int FreeFile(FILE *file)
Definition: fd.c:2226
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
XLogRecPtr begin
Definition: timeline.h:28
Definition: pg_list.h:45
#define TLHistoryFilePath(path, tli)
void restoreTimeLineHistoryFiles ( TimeLineID  begin,
TimeLineID  end 
)

Definition at line 48 of file timeline.c.

References KeepFileRestoredFromArchive(), MAXFNAMELEN, MAXPGPATH, RestoreArchivedFile(), and TLHistoryFileName.

Referenced by rescanLatestTimeLine(), and StartupXLOG().

49 {
50  char path[MAXPGPATH];
51  char histfname[MAXFNAMELEN];
52  TimeLineID tli;
53 
54  for (tli = begin; tli < end; tli++)
55  {
56  if (tli == 1)
57  continue;
58 
59  TLHistoryFileName(histfname, tli);
60  if (RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false))
61  KeepFileRestoredFromArchive(path, histfname);
62  }
63 }
uint32 TimeLineID
Definition: xlogdefs.h:45
void KeepFileRestoredFromArchive(char *path, char *xlogfname)
Definition: xlogarchive.c:426
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition: xlogarchive.c:51
#define MAXPGPATH
#define TLHistoryFileName(fname, tli)
#define MAXFNAMELEN
bool tliInHistory ( TimeLineID  tli,
List expectedTLEs 
)

Definition at line 506 of file timeline.c.

References lfirst.

Referenced by checkTimeLineSwitch(), and ReadRecord().

507 {
508  ListCell *cell;
509 
510  foreach(cell, expectedTLEs)
511  {
512  if (((TimeLineHistoryEntry *) lfirst(cell))->tli == tli)
513  return true;
514  }
515 
516  return false;
517 }
#define lfirst(lc)
Definition: pg_list.h:106
TimeLineID tliOfPointInHistory ( XLogRecPtr  ptr,
List history 
)

Definition at line 524 of file timeline.c.

References TimeLineHistoryEntry::begin, elog, TimeLineHistoryEntry::end, ERROR, lfirst, TimeLineHistoryEntry::tli, and XLogRecPtrIsInvalid.

Referenced by StartupXLOG(), and WaitForWALToBecomeAvailable().

525 {
526  ListCell *cell;
527 
528  foreach(cell, history)
529  {
531 
532  if ((XLogRecPtrIsInvalid(tle->begin) || tle->begin <= ptr) &&
533  (XLogRecPtrIsInvalid(tle->end) || ptr < tle->end))
534  {
535  /* found it */
536  return tle->tli;
537  }
538  }
539 
540  /* shouldn't happen. */
541  elog(ERROR, "timeline history was not contiguous");
542  return 0; /* keep compiler quiet */
543 }
TimeLineID tli
Definition: timeline.h:27
#define ERROR
Definition: elog.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
XLogRecPtr end
Definition: timeline.h:29
#define lfirst(lc)
Definition: pg_list.h:106
XLogRecPtr begin
Definition: timeline.h:28
#define elog
Definition: elog.h:219
XLogRecPtr tliSwitchPoint ( TimeLineID  tli,
List history,
TimeLineID nextTLI 
)

Definition at line 552 of file timeline.c.

References TimeLineHistoryEntry::end, ereport, errmsg(), ERROR, InvalidXLogRecPtr, lfirst, and TimeLineHistoryEntry::tli.

Referenced by StartReplication(), StartupXLOG(), and XLogSendPhysical().

553 {
554  ListCell *cell;
555 
556  if (nextTLI)
557  *nextTLI = 0;
558  foreach(cell, history)
559  {
561 
562  if (tle->tli == tli)
563  return tle->end;
564  if (nextTLI)
565  *nextTLI = tle->tli;
566  }
567 
568  ereport(ERROR,
569  (errmsg("requested timeline %u is not in this server's history",
570  tli)));
571  return InvalidXLogRecPtr; /* keep compiler quiet */
572 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
TimeLineID tli
Definition: timeline.h:27
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
XLogRecPtr end
Definition: timeline.h:29
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
void writeTimeLineHistory ( TimeLineID  newTLI,
TimeLineID  parentTLI,
XLogRecPtr  switchpoint,
char *  reason 
)

Definition at line 288 of file timeline.c.

References ArchiveRecoveryRequested, Assert, CloseTransientFile(), durable_link_or_rename(), ereport, errcode_for_file_access(), errmsg(), ERROR, fd(), MAXFNAMELEN, MAXPGPATH, OpenTransientFile(), pg_fsync(), read, RestoreArchivedFile(), snprintf(), TLHistoryFileName, TLHistoryFilePath, unlink(), write, XLogArchiveNotify(), XLogArchivingActive, and XLOGDIR.

Referenced by StartupXLOG().

290 {
291  char path[MAXPGPATH];
292  char tmppath[MAXPGPATH];
293  char histfname[MAXFNAMELEN];
294  char buffer[BLCKSZ];
295  int srcfd;
296  int fd;
297  int nbytes;
298 
299  Assert(newTLI > parentTLI); /* else bad selection of newTLI */
300 
301  /*
302  * Write into a temp file name.
303  */
304  snprintf(tmppath, MAXPGPATH, XLOGDIR "/xlogtemp.%d", (int) getpid());
305 
306  unlink(tmppath);
307 
308  /* do not use get_sync_bit() here --- want to fsync only at end of fill */
309  fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL,
310  S_IRUSR | S_IWUSR);
311  if (fd < 0)
312  ereport(ERROR,
314  errmsg("could not create file \"%s\": %m", tmppath)));
315 
316  /*
317  * If a history file exists for the parent, copy it verbatim
318  */
320  {
321  TLHistoryFileName(histfname, parentTLI);
322  RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
323  }
324  else
325  TLHistoryFilePath(path, parentTLI);
326 
327  srcfd = OpenTransientFile(path, O_RDONLY, 0);
328  if (srcfd < 0)
329  {
330  if (errno != ENOENT)
331  ereport(ERROR,
333  errmsg("could not open file \"%s\": %m", path)));
334  /* Not there, so assume parent has no parents */
335  }
336  else
337  {
338  for (;;)
339  {
340  errno = 0;
341  nbytes = (int) read(srcfd, buffer, sizeof(buffer));
342  if (nbytes < 0 || errno != 0)
343  ereport(ERROR,
345  errmsg("could not read file \"%s\": %m", path)));
346  if (nbytes == 0)
347  break;
348  errno = 0;
349  if ((int) write(fd, buffer, nbytes) != nbytes)
350  {
351  int save_errno = errno;
352 
353  /*
354  * If we fail to make the file, delete it to release disk
355  * space
356  */
357  unlink(tmppath);
358 
359  /*
360  * if write didn't set errno, assume problem is no disk space
361  */
362  errno = save_errno ? save_errno : ENOSPC;
363 
364  ereport(ERROR,
366  errmsg("could not write to file \"%s\": %m", tmppath)));
367  }
368  }
369  CloseTransientFile(srcfd);
370  }
371 
372  /*
373  * Append one line with the details of this timeline split.
374  *
375  * If we did have a parent file, insert an extra newline just in case the
376  * parent file failed to end with one.
377  */
378  snprintf(buffer, sizeof(buffer),
379  "%s%u\t%X/%X\t%s\n",
380  (srcfd < 0) ? "" : "\n",
381  parentTLI,
382  (uint32) (switchpoint >> 32), (uint32) (switchpoint),
383  reason);
384 
385  nbytes = strlen(buffer);
386  errno = 0;
387  if ((int) write(fd, buffer, nbytes) != nbytes)
388  {
389  int save_errno = errno;
390 
391  /*
392  * If we fail to make the file, delete it to release disk space
393  */
394  unlink(tmppath);
395  /* if write didn't set errno, assume problem is no disk space */
396  errno = save_errno ? save_errno : ENOSPC;
397 
398  ereport(ERROR,
400  errmsg("could not write to file \"%s\": %m", tmppath)));
401  }
402 
403  if (pg_fsync(fd) != 0)
404  ereport(ERROR,
406  errmsg("could not fsync file \"%s\": %m", tmppath)));
407 
408  if (CloseTransientFile(fd))
409  ereport(ERROR,
411  errmsg("could not close file \"%s\": %m", tmppath)));
412 
413 
414  /*
415  * Now move the completed history file into place with its final name.
416  */
417  TLHistoryFilePath(path, newTLI);
418 
419  /*
420  * Perform the rename using link if available, paranoidly trying to avoid
421  * overwriting an existing file (there shouldn't be one).
422  */
423  durable_link_or_rename(tmppath, path, ERROR);
424 
425  /* The history file can be archived immediately. */
426  if (XLogArchivingActive())
427  {
428  TLHistoryFileName(histfname, newTLI);
429  XLogArchiveNotify(histfname);
430  }
431 }
bool ArchiveRecoveryRequested
Definition: xlog.c:245
#define write(a, b, c)
Definition: win32.h:19
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition: xlogarchive.c:51
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void XLogArchiveNotify(const char *xlog)
Definition: xlogarchive.c:512
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define TLHistoryFileName(fname, tli)
int OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
Definition: fd.c:2093
int errcode_for_file_access(void)
Definition: elog.c:598
unsigned int uint32
Definition: c.h:265
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
int CloseTransientFile(int fd)
Definition: fd.c:2254
#define MAXFNAMELEN
#define XLOGDIR
#define Assert(condition)
Definition: c.h:671
#define XLogArchivingActive()
Definition: xlog.h:134
int durable_link_or_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
int pg_fsync(int fd)
Definition: fd.c:333
#define read(a, b, c)
Definition: win32.h:18
#define TLHistoryFilePath(path, tli)
void writeTimeLineHistoryFile ( TimeLineID  tli,
char *  content,
int  size 
)

Definition at line 441 of file timeline.c.

References CloseTransientFile(), durable_link_or_rename(), ereport, errcode_for_file_access(), errmsg(), ERROR, fd(), MAXPGPATH, OpenTransientFile(), pg_fsync(), snprintf(), TLHistoryFilePath, unlink(), write, and XLOGDIR.

Referenced by WalRcvFetchTimeLineHistoryFiles().

442 {
443  char path[MAXPGPATH];
444  char tmppath[MAXPGPATH];
445  int fd;
446 
447  /*
448  * Write into a temp file name.
449  */
450  snprintf(tmppath, MAXPGPATH, XLOGDIR "/xlogtemp.%d", (int) getpid());
451 
452  unlink(tmppath);
453 
454  /* do not use get_sync_bit() here --- want to fsync only at end of fill */
455  fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL,
456  S_IRUSR | S_IWUSR);
457  if (fd < 0)
458  ereport(ERROR,
460  errmsg("could not create file \"%s\": %m", tmppath)));
461 
462  errno = 0;
463  if ((int) write(fd, content, size) != size)
464  {
465  int save_errno = errno;
466 
467  /*
468  * If we fail to make the file, delete it to release disk space
469  */
470  unlink(tmppath);
471  /* if write didn't set errno, assume problem is no disk space */
472  errno = save_errno ? save_errno : ENOSPC;
473 
474  ereport(ERROR,
476  errmsg("could not write to file \"%s\": %m", tmppath)));
477  }
478 
479  if (pg_fsync(fd) != 0)
480  ereport(ERROR,
482  errmsg("could not fsync file \"%s\": %m", tmppath)));
483 
484  if (CloseTransientFile(fd))
485  ereport(ERROR,
487  errmsg("could not close file \"%s\": %m", tmppath)));
488 
489 
490  /*
491  * Now move the completed history file into place with its final name.
492  */
493  TLHistoryFilePath(path, tli);
494 
495  /*
496  * Perform the rename using link if available, paranoidly trying to avoid
497  * overwriting an existing file (there shouldn't be one).
498  */
499  durable_link_or_rename(tmppath, path, ERROR);
500 }
#define write(a, b, c)
Definition: win32.h:19
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
int OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
Definition: fd.c:2093
int errcode_for_file_access(void)
Definition: elog.c:598
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
int CloseTransientFile(int fd)
Definition: fd.c:2254
#define XLOGDIR
int durable_link_or_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
int pg_fsync(int fd)
Definition: fd.c:333
#define TLHistoryFilePath(path, tli)