PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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/xlogarchive.h"
#include "access/xlogdefs.h"
#include "pgstat.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

◆ existsTimeLineHistory()

bool existsTimeLineHistory ( TimeLineID  probeTLI)

Definition at line 222 of file timeline.c.

223{
224 char path[MAXPGPATH];
226 FILE *fd;
227
228 /* Timeline 1 does not have a history file, so no need to check */
229 if (probeTLI == 1)
230 return false;
231
233 {
235 RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
236 }
237 else
239
240 fd = AllocateFile(path, "r");
241 if (fd != NULL)
242 {
243 FreeFile(fd);
244 return true;
245 }
246 else
247 {
248 if (errno != ENOENT)
251 errmsg("could not open file \"%s\": %m", path)));
252 return false;
253 }
254}
int errcode_for_file_access(void)
Definition elog.c:886
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define FATAL
Definition elog.h:41
#define ereport(elevel,...)
Definition elog.h:150
int FreeFile(FILE *file)
Definition fd.c:2823
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2624
#define MAXPGPATH
static int fd(const char *x, int i)
static int fb(int x)
#define MAXFNAMELEN
static void TLHistoryFilePath(char *path, TimeLineID tli)
static void TLHistoryFileName(char *fname, TimeLineID tli)
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition xlogarchive.c:54
bool ArchiveRecoveryRequested

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

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

◆ findNewestTimeLine()

TimeLineID findNewestTimeLine ( TimeLineID  startTLI)

Definition at line 264 of file timeline.c.

265{
268
269 /*
270 * The algorithm is just to probe for the existence of timeline history
271 * files. XXX is it useful to allow gaps in the sequence?
272 */
274
275 for (probeTLI = startTLI + 1;; probeTLI++)
276 {
278 {
279 newestTLI = probeTLI; /* probeTLI exists */
280 }
281 else
282 {
283 /* doesn't exist, assume we're done */
284 break;
285 }
286 }
287
288 return newestTLI;
289}
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition timeline.c:222
uint32 TimeLineID
Definition xlogdefs.h:63

References existsTimeLineHistory(), and fb().

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

◆ readTimeLineHistory()

List * readTimeLineHistory ( TimeLineID  targetTLI)

Definition at line 76 of file timeline.c.

77{
78 List *result;
79 char path[MAXPGPATH];
81 FILE *fd;
85 bool fromArchive = false;
86
87 /* Timeline 1 does not have a history file, so no need to check */
88 if (targetTLI == 1)
89 {
91 entry->tli = targetTLI;
92 entry->begin = entry->end = InvalidXLogRecPtr;
93 return list_make1(entry);
94 }
95
97 {
100 RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
101 }
102 else
104
105 fd = AllocateFile(path, "r");
106 if (fd == NULL)
107 {
108 if (errno != ENOENT)
111 errmsg("could not open file \"%s\": %m", path)));
112 /* Not there, so assume no parents */
114 entry->tli = targetTLI;
115 entry->begin = entry->end = InvalidXLogRecPtr;
116 return list_make1(entry);
117 }
118
119 result = NIL;
120
121 /*
122 * Parse the file...
123 */
125 for (;;)
126 {
127 char fline[MAXPGPATH];
128 char *res;
129 char *ptr;
130 TimeLineID tli;
133 int nfields;
134
136 res = fgets(fline, sizeof(fline), fd);
138 if (res == NULL)
139 {
140 if (ferror(fd))
143 errmsg("could not read file \"%s\": %m", path)));
144
145 break;
146 }
147
148 /* skip leading whitespace and check for # comment */
149 for (ptr = fline; *ptr; ptr++)
150 {
151 if (!isspace((unsigned char) *ptr))
152 break;
153 }
154 if (*ptr == '\0' || *ptr == '#')
155 continue;
156
157 nfields = sscanf(fline, "%u\t%X/%08X", &tli, &switchpoint_hi, &switchpoint_lo);
158
159 if (nfields < 1)
160 {
161 /* expect a numeric timeline ID as first field of line */
163 (errmsg("syntax error in history file: %s", fline),
164 errhint("Expected a numeric timeline ID.")));
165 }
166 if (nfields != 3)
168 (errmsg("syntax error in history file: %s", fline),
169 errhint("Expected a write-ahead log switchpoint location.")));
170
171 if (result && tli <= lasttli)
173 (errmsg("invalid data in history file: %s", fline),
174 errhint("Timeline IDs must be in increasing sequence.")));
175
176 lasttli = tli;
177
179 entry->tli = tli;
180 entry->begin = prevend;
181 entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
182 prevend = entry->end;
183
184 /* Build list with newest item first */
185 result = lcons(entry, result);
186
187 /* we ignore the remainder of each line */
188 }
189
190 FreeFile(fd);
191
192 if (result && targetTLI <= lasttli)
194 (errmsg("invalid data in history file \"%s\"", path),
195 errhint("Timeline IDs must be less than child timeline's ID.")));
196
197 /*
198 * Create one more entry for the "tip" of the timeline, which has no entry
199 * in the history file.
200 */
202 entry->tli = targetTLI;
203 entry->begin = prevend;
204 entry->end = InvalidXLogRecPtr;
205
206 result = lcons(entry, result);
207
208 /*
209 * If the history file was fetched from archive, save it in pg_wal for
210 * future reference.
211 */
212 if (fromArchive)
214
215 return result;
216}
uint64_t uint64
Definition c.h:557
uint32_t uint32
Definition c.h:556
int errhint(const char *fmt,...)
Definition elog.c:1330
#define ERROR
Definition elog.h:39
#define palloc_object(type)
Definition fe_memutils.h:74
List * lcons(void *datum, List *list)
Definition list.c:495
#define NIL
Definition pg_list.h:68
#define list_make1(x1)
Definition pg_list.h:212
Definition pg_list.h:54
XLogRecPtr begin
Definition timeline.h:28
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:69
static void pgstat_report_wait_end(void)
Definition wait_event.h:85
void KeepFileRestoredFromArchive(const char *path, const char *xlogfname)
uint64 XLogRecPtr
Definition xlogdefs.h:21
#define InvalidXLogRecPtr
Definition xlogdefs.h:28

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

Referenced by AddWALInfoToBackupManifest(), GetOldestUnsummarizedLSN(), PrepareForIncrementalBackup(), ReadReplicationSlot(), rescanLatestTimeLine(), StartReplication(), summarizer_read_local_xlog_page(), WaitForWALToBecomeAvailable(), WalSummarizerMain(), XLogFileReadAnyTLI(), XLogReadDetermineTimeline(), and XLogSendPhysical().

◆ restoreTimeLineHistoryFiles()

void restoreTimeLineHistoryFiles ( TimeLineID  begin,
TimeLineID  end 
)

Definition at line 50 of file timeline.c.

51{
52 char path[MAXPGPATH];
54 TimeLineID tli;
55
56 for (tli = begin; tli < end; tli++)
57 {
58 if (tli == 1)
59 continue;
60
62 if (RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false))
64 }
65}

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

Referenced by rescanLatestTimeLine(), and StartupXLOG().

◆ tliInHistory()

bool tliInHistory ( TimeLineID  tli,
List expectedTLEs 
)

Definition at line 526 of file timeline.c.

527{
528 ListCell *cell;
529
530 foreach(cell, expectedTLEs)
531 {
532 if (((TimeLineHistoryEntry *) lfirst(cell))->tli == tli)
533 return true;
534 }
535
536 return false;
537}
#define lfirst(lc)
Definition pg_list.h:172
static List * expectedTLEs

References expectedTLEs, and lfirst.

Referenced by checkTimeLineSwitch(), and ReadRecord().

◆ tliOfPointInHistory()

TimeLineID tliOfPointInHistory ( XLogRecPtr  ptr,
List history 
)

Definition at line 544 of file timeline.c.

545{
546 ListCell *cell;
547
548 foreach(cell, history)
549 {
551
552 if ((!XLogRecPtrIsValid(tle->begin) || tle->begin <= ptr) &&
553 (!XLogRecPtrIsValid(tle->end) || ptr < tle->end))
554 {
555 /* found it */
556 return tle->tli;
557 }
558 }
559
560 /* shouldn't happen. */
561 elog(ERROR, "timeline history was not contiguous");
562 return 0; /* keep compiler quiet */
563}
#define elog(elevel,...)
Definition elog.h:226
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29

References elog, ERROR, fb(), lfirst, TimeLineHistoryEntry::tli, and XLogRecPtrIsValid.

Referenced by InitWalRecovery(), ReadReplicationSlot(), WaitForWALToBecomeAvailable(), and XLogReadDetermineTimeline().

◆ tliSwitchPoint()

XLogRecPtr tliSwitchPoint ( TimeLineID  tli,
List history,
TimeLineID nextTLI 
)

Definition at line 572 of file timeline.c.

573{
574 ListCell *cell;
575
576 if (nextTLI)
577 *nextTLI = 0;
578 foreach(cell, history)
579 {
581
582 if (tle->tli == tli)
583 return tle->end;
584 if (nextTLI)
585 *nextTLI = tle->tli;
586 }
587
589 (errmsg("requested timeline %u is not in this server's history",
590 tli)));
591 return InvalidXLogRecPtr; /* keep compiler quiet */
592}

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

Referenced by InitWalRecovery(), StartReplication(), summarizer_read_local_xlog_page(), WalSummarizerMain(), XLogReadDetermineTimeline(), and XLogSendPhysical().

◆ writeTimeLineHistory()

void writeTimeLineHistory ( TimeLineID  newTLI,
TimeLineID  parentTLI,
XLogRecPtr  switchpoint,
char reason 
)

Definition at line 304 of file timeline.c.

306{
307 char path[MAXPGPATH];
308 char tmppath[MAXPGPATH];
310 char buffer[BLCKSZ];
311 int srcfd;
312 int fd;
313 int nbytes;
314
315 Assert(newTLI > parentTLI); /* else bad selection of newTLI */
316
317 /*
318 * Write into a temp file name.
319 */
320 snprintf(tmppath, MAXPGPATH, XLOGDIR "/xlogtemp.%d", (int) getpid());
321
323
324 /* do not use get_sync_bit() here --- want to fsync only at end of fill */
326 if (fd < 0)
329 errmsg("could not create file \"%s\": %m", tmppath)));
330
331 /*
332 * If a history file exists for the parent, copy it verbatim
333 */
335 {
337 RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
338 }
339 else
341
343 if (srcfd < 0)
344 {
345 if (errno != ENOENT)
348 errmsg("could not open file \"%s\": %m", path)));
349 /* Not there, so assume parent has no parents */
350 }
351 else
352 {
353 for (;;)
354 {
355 errno = 0;
357 nbytes = (int) read(srcfd, buffer, sizeof(buffer));
359 if (nbytes < 0 || errno != 0)
362 errmsg("could not read file \"%s\": %m", path)));
363 if (nbytes == 0)
364 break;
365 errno = 0;
367 if ((int) write(fd, buffer, nbytes) != nbytes)
368 {
369 int save_errno = errno;
370
371 /*
372 * If we fail to make the file, delete it to release disk
373 * space
374 */
376
377 /*
378 * if write didn't set errno, assume problem is no disk space
379 */
381
384 errmsg("could not write to file \"%s\": %m", tmppath)));
385 }
387 }
388
389 if (CloseTransientFile(srcfd) != 0)
392 errmsg("could not close file \"%s\": %m", path)));
393 }
394
395 /*
396 * Append one line with the details of this timeline split.
397 *
398 * If we did have a parent file, insert an extra newline just in case the
399 * parent file failed to end with one.
400 */
401 snprintf(buffer, sizeof(buffer),
402 "%s%u\t%X/%08X\t%s\n",
403 (srcfd < 0) ? "" : "\n",
404 parentTLI,
406 reason);
407
408 nbytes = strlen(buffer);
409 errno = 0;
411 if ((int) write(fd, buffer, nbytes) != nbytes)
412 {
413 int save_errno = errno;
414
415 /*
416 * If we fail to make the file, delete it to release disk space
417 */
419 /* if write didn't set errno, assume problem is no disk space */
421
424 errmsg("could not write to file \"%s\": %m", tmppath)));
425 }
427
429 if (pg_fsync(fd) != 0)
432 errmsg("could not fsync file \"%s\": %m", tmppath)));
434
435 if (CloseTransientFile(fd) != 0)
438 errmsg("could not close file \"%s\": %m", tmppath)));
439
440 /*
441 * Now move the completed history file into place with its final name.
442 */
444 Assert(access(path, F_OK) != 0 && errno == ENOENT);
446
447 /* The history file can be archived immediately. */
449 {
452 }
453}
#define Assert(condition)
Definition c.h:883
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition fd.c:779
int CloseTransientFile(int fd)
Definition fd.c:2851
int data_sync_elevel(int elevel)
Definition fd.c:3982
int pg_fsync(int fd)
Definition fd.c:386
int OpenTransientFile(const char *fileName, int fileFlags)
Definition fd.c:2674
#define write(a, b, c)
Definition win32.h:14
#define read(a, b, c)
Definition win32.h:13
#define snprintf
Definition port.h:260
short access
#define XLogArchivingActive()
Definition xlog.h:101
#define XLOGDIR
void XLogArchiveNotify(const char *xlog)
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47

References ArchiveRecoveryRequested, Assert, CloseTransientFile(), data_sync_elevel(), durable_rename(), ereport, errcode_for_file_access(), errmsg(), ERROR, fb(), fd(), LSN_FORMAT_ARGS, MAXFNAMELEN, MAXPGPATH, OpenTransientFile(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), read, RestoreArchivedFile(), snprintf, TLHistoryFileName(), TLHistoryFilePath(), write, XLogArchiveNotify(), XLogArchivingActive, and XLOGDIR.

Referenced by StartupXLOG().

◆ writeTimeLineHistoryFile()

void writeTimeLineHistoryFile ( TimeLineID  tli,
char content,
int  size 
)

Definition at line 463 of file timeline.c.

464{
465 char path[MAXPGPATH];
466 char tmppath[MAXPGPATH];
467 int fd;
468
469 /*
470 * Write into a temp file name.
471 */
472 snprintf(tmppath, MAXPGPATH, XLOGDIR "/xlogtemp.%d", (int) getpid());
473
475
476 /* do not use get_sync_bit() here --- want to fsync only at end of fill */
478 if (fd < 0)
481 errmsg("could not create file \"%s\": %m", tmppath)));
482
483 errno = 0;
485 if ((int) write(fd, content, size) != size)
486 {
487 int save_errno = errno;
488
489 /*
490 * If we fail to make the file, delete it to release disk space
491 */
493 /* if write didn't set errno, assume problem is no disk space */
495
498 errmsg("could not write to file \"%s\": %m", tmppath)));
499 }
501
503 if (pg_fsync(fd) != 0)
506 errmsg("could not fsync file \"%s\": %m", tmppath)));
508
509 if (CloseTransientFile(fd) != 0)
512 errmsg("could not close file \"%s\": %m", tmppath)));
513
514 /*
515 * Now move the completed history file into place with its final name,
516 * replacing any existing file with the same name.
517 */
518 TLHistoryFilePath(path, tli);
520}

References CloseTransientFile(), data_sync_elevel(), durable_rename(), ereport, errcode_for_file_access(), errmsg(), ERROR, fb(), fd(), MAXPGPATH, OpenTransientFile(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), snprintf, TLHistoryFilePath(), write, and XLOGDIR.

Referenced by WalRcvFetchTimeLineHistoryFiles().