PostgreSQL Source Code git master
Loading...
Searching...
No Matches
xlogrecovery.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * xlogrecovery.c
4 * Functions for WAL recovery, standby mode
5 *
6 * This source file contains functions controlling WAL recovery.
7 * InitWalRecovery() initializes the system for crash or archive recovery,
8 * or standby mode, depending on configuration options and the state of
9 * the control file and possible backup label file. PerformWalRecovery()
10 * performs the actual WAL replay, calling the rmgr-specific redo routines.
11 * FinishWalRecovery() performs end-of-recovery checks and cleanup actions,
12 * and prepares information needed to initialize the WAL for writes. In
13 * addition to these three main functions, there are a bunch of functions
14 * for interrogating recovery state and controlling the recovery process.
15 *
16 *
17 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
18 * Portions Copyright (c) 1994, Regents of the University of California
19 *
20 * src/backend/access/transam/xlogrecovery.c
21 *
22 *-------------------------------------------------------------------------
23 */
24
25#include "postgres.h"
26
27#include <ctype.h>
28#include <time.h>
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <unistd.h>
32
33#include "access/timeline.h"
34#include "access/transam.h"
35#include "access/xact.h"
37#include "access/xlogarchive.h"
39#include "access/xlogreader.h"
40#include "access/xlogrecovery.h"
41#include "access/xlogutils.h"
42#include "access/xlogwait.h"
43#include "backup/basebackup.h"
44#include "catalog/pg_control.h"
45#include "commands/tablespace.h"
46#include "common/file_utils.h"
47#include "miscadmin.h"
48#include "nodes/miscnodes.h"
49#include "pgstat.h"
50#include "postmaster/bgwriter.h"
51#include "postmaster/startup.h"
52#include "replication/slot.h"
55#include "storage/fd.h"
56#include "storage/ipc.h"
57#include "storage/latch.h"
58#include "storage/pmsignal.h"
59#include "storage/procarray.h"
60#include "storage/spin.h"
61#include "storage/subsystems.h"
62#include "utils/datetime.h"
63#include "utils/fmgrprotos.h"
64#include "utils/guc.h"
65#include "utils/guc_hooks.h"
67#include "utils/pg_lsn.h"
68#include "utils/ps_status.h"
69#include "utils/pg_rusage.h"
70#include "utils/wait_event.h"
71
72/* Unsupported old recovery command file names (relative to $PGDATA) */
73#define RECOVERY_COMMAND_FILE "recovery.conf"
74#define RECOVERY_COMMAND_DONE "recovery.done"
75
76/*
77 * GUC support
78 */
80 {"pause", RECOVERY_TARGET_ACTION_PAUSE, false},
81 {"promote", RECOVERY_TARGET_ACTION_PROMOTE, false},
82 {"shutdown", RECOVERY_TARGET_ACTION_SHUTDOWN, false},
83 {NULL, 0, false}
84};
85
86/* options formerly taken from recovery.conf for archive recovery */
99
100/* options formerly taken from recovery.conf for XLOG streaming */
104
105/*
106 * recoveryTargetTimeLineGoal: what the user requested, if any
107 *
108 * recoveryTargetTLIRequested: numeric value of requested timeline, if constant
109 *
110 * recoveryTargetTLI: the currently understood target timeline; changes
111 *
112 * expectedTLEs: a list of TimeLineHistoryEntries for recoveryTargetTLI and
113 * the timelines of its known parents, newest first (so recoveryTargetTLI is
114 * always the first list member). Only these TLIs are expected to be seen in
115 * the WAL segments we read, and indeed only these TLIs will be considered as
116 * candidate WAL files to open at all.
117 *
118 * curFileTLI: the TLI appearing in the name of the current input WAL file.
119 * (This is not necessarily the same as the timeline from which we are
120 * replaying WAL, which StartupXLOG calls replayTLI, because we could be
121 * scanning data that was copied from an ancestor timeline when the current
122 * file was created.) During a sequential scan we do not allow this value
123 * to decrease.
124 */
130
131/*
132 * When ArchiveRecoveryRequested is set, archive recovery was requested,
133 * ie. signal files were present. When InArchiveRecovery is set, we are
134 * currently recovering using offline XLOG archives. These variables are only
135 * valid in the startup process.
136 *
137 * When ArchiveRecoveryRequested is true, but InArchiveRecovery is false, we're
138 * currently performing crash recovery using only XLOG files in pg_wal, but
139 * will switch to using offline XLOG archives as soon as we reach the end of
140 * WAL in pg_wal.
141 */
143bool InArchiveRecovery = false;
144
145/*
146 * When StandbyModeRequested is set, standby mode was requested, i.e.
147 * standby.signal file was present. When StandbyMode is set, we are currently
148 * in standby mode. These variables are only valid in the startup process.
149 * They work similarly to ArchiveRecoveryRequested and InArchiveRecovery.
150 */
151static bool StandbyModeRequested = false;
152bool StandbyMode = false;
153
154/* was a signal file present at startup? */
155static bool standby_signal_file_found = false;
156static bool recovery_signal_file_found = false;
157
158/*
159 * CheckPointLoc is the position of the checkpoint record that determines
160 * where to start the replay. It comes from the backup label file or the
161 * control file.
162 *
163 * RedoStartLSN is the checkpoint's REDO location, also from the backup label
164 * file or the control file. In standby mode, XLOG streaming usually starts
165 * from the position where an invalid record was found. But if we fail to
166 * read even the initial checkpoint record, we use the REDO location instead
167 * of the checkpoint location as the start position of XLOG streaming.
168 * Otherwise we would have to jump backwards to the REDO location after
169 * reading the checkpoint record, because the REDO record can precede the
170 * checkpoint record.
171 */
176
177/*
178 * Local copy of SharedHotStandbyActive variable. False actually means "not
179 * known, need to check the shared state".
180 */
181static bool LocalHotStandbyActive = false;
182
183/*
184 * Local copy of SharedPromoteIsTriggered variable. False actually means "not
185 * known, need to check the shared state".
186 */
187static bool LocalPromoteIsTriggered = false;
188
189/* Has the recovery code requested a walreceiver wakeup? */
191
192/* XLogReader object used to parse the WAL records */
194
195/* XLogPrefetcher object used to consume WAL records with read-ahead */
197
198/* Parameters passed down from ReadRecord to the XLogPageRead callback. */
200{
201 int emode;
202 bool fetching_ckpt; /* are we fetching a checkpoint record? */
206
207/* flag to tell XLogPageRead that we have started replaying */
208static bool InRedo = false;
209
210/*
211 * Codes indicating where we got a WAL file from during recovery, or where
212 * to attempt to get one.
213 */
214typedef enum
215{
216 XLOG_FROM_ANY = 0, /* request to read WAL from any source */
217 XLOG_FROM_ARCHIVE, /* restored using restore_command */
218 XLOG_FROM_PG_WAL, /* existing file in pg_wal */
219 XLOG_FROM_STREAM, /* streamed from primary */
220} XLogSource;
221
222/* human-readable names for XLogSources, for debugging output */
223static const char *const xlogSourceNames[] = {"any", "archive", "pg_wal", "stream"};
224
225/*
226 * readFile is -1 or a kernel FD for the log file segment that's currently
227 * open for reading. readSegNo identifies the segment. readOff is the offset
228 * of the page just read, readLen indicates how much of it has been read into
229 * readBuf, and readSource indicates where we got the currently open file from.
230 *
231 * Note: we could use Reserve/ReleaseExternalFD to track consumption of this
232 * FD too (like for openLogFile in xlog.c); but it doesn't currently seem
233 * worthwhile, since the XLOG is not read by general-purpose sessions.
234 */
235static int readFile = -1;
237static uint32 readOff = 0;
238static uint32 readLen = 0;
240
241/*
242 * Keeps track of which source we're currently reading from. This is
243 * different from readSource in that this is always set, even when we don't
244 * currently have a WAL file open. If lastSourceFailed is set, our last
245 * attempt to read from currentSource failed, and we should try another source
246 * next.
247 *
248 * pendingWalRcvRestart is set when a config change occurs that requires a
249 * walreceiver restart. This is only valid in XLOG_FROM_STREAM state.
250 */
252static bool lastSourceFailed = false;
253static bool pendingWalRcvRestart = false;
254
255/*
256 * These variables track when we last obtained some WAL data to process,
257 * and where we got it from. (XLogReceiptSource is initially the same as
258 * readSource, but readSource gets reset to zero when we don't have data
259 * to process right now. It is also different from currentSource, which
260 * also changes when we try to read from a source and fail, while
261 * XLogReceiptSource tracks where we last successfully read some WAL.)
262 */
265
266/* Local copy of WalRcv->flushedUpto */
269
270/*
271 * Copy of minRecoveryPoint and backupEndPoint from the control file.
272 *
273 * In order to reach consistency, we must replay the WAL up to
274 * minRecoveryPoint. If backupEndRequired is true, we must also reach
275 * backupEndPoint, or if it's invalid, an end-of-backup record corresponding
276 * to backupStartPoint.
277 *
278 * Note: In archive recovery, after consistency has been reached, the
279 * functions in xlog.c will start updating minRecoveryPoint in the control
280 * file. But this copy of minRecoveryPoint variable reflects the value at the
281 * beginning of recovery, and is *not* updated after consistency is reached.
282 */
285
288static bool backupEndRequired = false;
289
290/*
291 * Have we reached a consistent database state? In crash recovery, we have
292 * to replay all the WAL, so reachedConsistency is never set. During archive
293 * recovery, the database is consistent once minRecoveryPoint is reached.
294 *
295 * Consistent state means that the system is internally consistent, all
296 * the WAL has been replayed up to a certain point, and importantly, there
297 * is no trace of later actions on disk.
298 *
299 * This flag is used only by the startup process and postmaster. When
300 * minRecoveryPoint is reached, the startup process sets it to true and
301 * sends a PMSIGNAL_RECOVERY_CONSISTENT signal to the postmaster,
302 * which then sets it to true upon receiving the signal.
303 */
305
306/* Buffers dedicated to consistency checks of size BLCKSZ */
309
311
312static void XLogRecoveryShmemRequest(void *arg);
313static void XLogRecoveryShmemInit(void *arg);
314
319
320/*
321 * abortedRecPtr is the start pointer of a broken record at end of WAL when
322 * recovery completes; missingContrecPtr is the location of the first
323 * contrecord that went missing. See CreateOverwriteContrecordRecord for
324 * details.
325 */
328
329/*
330 * if recoveryStopsBefore/After returns true, it saves information of the stop
331 * point here
332 */
338
339/* prototypes for local functions */
340static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI);
341
342static void EnableStandbyMode(void);
343static void readRecoverySignalFile(void);
344static void validateRecoveryParameters(void);
348static bool read_tablespace_map(List **tablespaces);
349
350static void xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI);
351static void CheckRecoveryConsistency(void);
352static void rm_redo_error_callback(void *arg);
353#ifdef WAL_DEBUG
354static void xlog_outrec(StringInfo buf, XLogReaderState *record);
355#endif
356static void xlog_block_info(StringInfo buf, XLogReaderState *record);
358 TimeLineID prevTLI, TimeLineID replayTLI);
361
362static bool recoveryStopsBefore(XLogReaderState *record);
363static bool recoveryStopsAfter(XLogReaderState *record);
364static char *getRecoveryStopReason(void);
365static void recoveryPausesHere(bool endOfRecovery);
366static bool recoveryApplyDelay(XLogReaderState *record);
367static void ConfirmRecoveryPaused(void);
368
370 int emode, bool fetching_ckpt,
371 TimeLineID replayTLI);
372
374 int reqLen, XLogRecPtr targetRecPtr, char *readBuf);
376 bool randAccess,
377 bool fetching_ckpt,
379 TimeLineID replayTLI,
381 bool nonblocking);
382static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr);
384 XLogRecPtr RecPtr, TimeLineID replayTLI);
386static int XLogFileRead(XLogSegNo segno, TimeLineID tli,
389
390static bool CheckForStandbyTrigger(void);
391static void SetPromoteIsTriggered(void);
392static bool HotStandbyActiveInReplay(void);
393
395static void SetLatestXTime(TimestampTz xtime);
397
398/*
399 * Register shared memory for WAL recovery
400 */
401static void
403{
404 ShmemRequestStruct(.name = "XLOG Recovery Ctl",
405 .size = sizeof(XLogRecoveryCtlData),
406 .ptr = (void **) &XLogRecoveryCtl,
407 );
408}
409
410static void
419
420/*
421 * A thin wrapper to enable StandbyMode and do other preparatory work as
422 * needed.
423 */
424static void
426{
427 StandbyMode = true;
428
429 /*
430 * To avoid server log bloat, we don't report recovery progress in a
431 * standby as it will always be in recovery unless promoted. We disable
432 * startup progress timeout in standby mode to avoid calling
433 * startup_progress_timeout_handler() unnecessarily.
434 */
436}
437
438/*
439 * Prepare the system for WAL recovery, if needed.
440 *
441 * This is called by StartupXLOG() which coordinates the server startup
442 * sequence. This function analyzes the control file and the backup label
443 * file, if any, and figures out whether we need to perform crash recovery or
444 * archive recovery, and how far we need to replay the WAL to reach a
445 * consistent state.
446 *
447 * This doesn't yet change the on-disk state, except for creating the symlinks
448 * from table space map file if any, and for fetching WAL files needed to find
449 * the checkpoint record. On entry, the caller has already read the control
450 * file into memory, and passes it as argument. This function updates it to
451 * reflect the recovery state, and the caller is expected to write it back to
452 * disk after initializing other subsystems, but before calling
453 * PerformWalRecovery().
454 *
455 * This initializes some global variables like ArchiveRecoveryRequested, and
456 * StandbyModeRequested and InRecovery.
457 */
458void
461{
462 XLogPageReadPrivate *private;
463 struct stat st;
464 bool wasShutdown;
465 XLogRecord *record;
467 bool haveTblspcMap = false;
468 bool haveBackupLabel = false;
469 CheckPoint checkPoint;
470 bool backupFromStandby = false;
471
473
474 /*
475 * Initialize on the assumption we want to recover to the latest timeline
476 * that's active according to pg_control.
477 */
481 else
483
484 /*
485 * Check for signal files, and if so set up state for offline recovery
486 */
489
490 /*
491 * Take ownership of the wakeup latch if we're going to sleep during
492 * recovery, if required.
493 */
496
497 /*
498 * Set the WAL reading processor now, as it will be needed when reading
499 * the checkpoint record required (backup_label or not).
500 */
502 xlogreader =
504 XL_ROUTINE(.page_read = &XLogPageRead,
505 .segment_open = NULL,
506 .segment_close = wal_segment_close),
507 private);
508 if (!xlogreader)
511 errmsg("out of memory"),
512 errdetail("Failed while allocating a WAL reading processor.")));
514
515 /*
516 * Set the WAL decode buffer size. This limits how far ahead we can read
517 * in the WAL.
518 */
520
521 /* Create a WAL prefetcher. */
523
524 /*
525 * Allocate two page buffers dedicated to WAL consistency checks. We do
526 * it this way, rather than just making static arrays, for two reasons:
527 * (1) no need to waste the storage in most instantiations of the backend;
528 * (2) a static char array isn't guaranteed to have any particular
529 * alignment, whereas palloc() will provide MAXALIGN'd storage.
530 */
533
534 /*
535 * Read the backup_label file. We want to run this part of the recovery
536 * process after checking for signal files and after performing validation
537 * of the recovery parameters.
538 */
541 {
542 List *tablespaces = NIL;
543
544 /*
545 * Archive recovery was requested, and thanks to the backup label
546 * file, we know how far we need to replay to reach consistency. Enter
547 * archive recovery directly.
548 */
549 InArchiveRecovery = true;
552
553 /*
554 * Omitting backup_label when creating a new replica, PITR node etc.
555 * unfortunately is a common cause of corruption. Logging that
556 * backup_label was used makes it a bit easier to exclude that as the
557 * cause of observed corruption.
558 *
559 * Do so before we try to read the checkpoint record (which can fail),
560 * as otherwise it can be hard to understand why a checkpoint other
561 * than ControlFile->checkPoint is used.
562 */
563 ereport(LOG,
564 errmsg("starting backup recovery with redo LSN %X/%08X, checkpoint LSN %X/%08X, on timeline ID %u",
568
569 /*
570 * When a backup_label file is present, we want to roll forward from
571 * the checkpoint it identifies, rather than using pg_control.
572 */
575 if (record != NULL)
576 {
577 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
580 errmsg_internal("checkpoint record is at %X/%08X",
582 InRecovery = true; /* force recovery even if SHUTDOWNED */
583
584 /*
585 * Make sure that REDO location exists. This may not be the case
586 * if there was a crash during an online backup, which left a
587 * backup_label around that references a WAL segment that's
588 * already been archived.
589 */
590 if (checkPoint.redo < CheckPointLoc)
591 {
593 if (!ReadRecord(xlogprefetcher, LOG, false,
594 checkPoint.ThisTimeLineID))
596 errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
598 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
599 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
600 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
602 }
603 }
604 else
605 {
607 errmsg("could not locate required checkpoint record at %X/%08X",
609 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
610 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
611 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
613 wasShutdown = false; /* keep compiler quiet */
614 }
615
616 /* Read the tablespace_map file if present and create symlinks. */
617 if (read_tablespace_map(&tablespaces))
618 {
619 ListCell *lc;
620
621 foreach(lc, tablespaces)
622 {
624 char *linkloc;
625
626 linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid);
627
628 /*
629 * Remove the existing symlink if any and Create the symlink
630 * under PGDATA.
631 */
633
634 if (symlink(ti->path, linkloc) < 0)
637 errmsg("could not create symbolic link \"%s\": %m",
638 linkloc)));
639
640 pfree(ti->path);
641 pfree(ti);
642 }
643
644 /* tell the caller to delete it later */
645 haveTblspcMap = true;
646 }
647
648 /* tell the caller to delete it later */
649 haveBackupLabel = true;
650 }
651 else
652 {
653 /* No backup_label file has been found if we are here. */
654
655 /*
656 * If tablespace_map file is present without backup_label file, there
657 * is no use of such file. There is no harm in retaining it, but it
658 * is better to get rid of the map file so that we don't have any
659 * redundant file in data directory and it will avoid any sort of
660 * confusion. It seems prudent though to just rename the file out of
661 * the way rather than delete it completely, also we ignore any error
662 * that occurs in rename operation as even if map file is present
663 * without backup_label file, it is harmless.
664 */
665 if (stat(TABLESPACE_MAP, &st) == 0)
666 {
669 ereport(LOG,
670 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
672 errdetail("File \"%s\" was renamed to \"%s\".",
674 else
675 ereport(LOG,
676 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
678 errdetail("Could not rename file \"%s\" to \"%s\": %m.",
680 }
681
682 /*
683 * It's possible that archive recovery was requested, but we don't
684 * know how far we need to replay the WAL before we reach consistency.
685 * This can happen for example if a base backup is taken from a
686 * running server using an atomic filesystem snapshot, without calling
687 * pg_backup_start/stop. Or if you just kill a running primary server
688 * and put it into archive recovery by creating a recovery signal
689 * file.
690 *
691 * Our strategy in that case is to perform crash recovery first,
692 * replaying all the WAL present in pg_wal, and only enter archive
693 * recovery after that.
694 *
695 * But usually we already know how far we need to replay the WAL (up
696 * to minRecoveryPoint, up to backupEndPoint, or until we see an
697 * end-of-backup record), and we can enter archive recovery directly.
698 */
704 {
705 InArchiveRecovery = true;
708 }
709
710 /*
711 * For the same reason as when starting up with backup_label present,
712 * emit a log message when we continue initializing from a base
713 * backup.
714 */
716 ereport(LOG,
717 errmsg("restarting backup recovery with redo LSN %X/%08X",
719
720 /* Get the last valid checkpoint record. */
727 if (record != NULL)
728 {
730 errmsg_internal("checkpoint record is at %X/%08X",
732 }
733 else
734 {
735 /*
736 * We used to attempt to go back to a secondary checkpoint record
737 * here, but only when not in standby mode. We now just fail if we
738 * can't read the last checkpoint because this allows us to
739 * simplify processing around checkpoints.
740 */
742 errmsg("could not locate a valid checkpoint record at %X/%08X",
744 }
745 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
747
748 /* Make sure that REDO location exists. */
749 if (checkPoint.redo < CheckPointLoc)
750 {
752 if (!ReadRecord(xlogprefetcher, LOG, false, checkPoint.ThisTimeLineID))
754 errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
756 }
757 }
758
760 {
762 ereport(LOG,
763 (errmsg("entering standby mode")));
765 ereport(LOG,
766 (errmsg("starting point-in-time recovery to XID %u",
769 ereport(LOG,
770 (errmsg("starting point-in-time recovery to %s",
773 ereport(LOG,
774 (errmsg("starting point-in-time recovery to \"%s\"",
777 ereport(LOG,
778 errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%08X\"",
781 ereport(LOG,
782 (errmsg("starting point-in-time recovery to earliest consistent point")));
783 else
784 ereport(LOG,
785 (errmsg("starting archive recovery")));
786 }
787
788 /*
789 * If the location of the checkpoint record is not on the expected
790 * timeline in the history of the requested timeline, we cannot proceed:
791 * the backup is not part of the history of the requested timeline.
792 */
793 Assert(expectedTLEs); /* was initialized by reading checkpoint
794 * record */
797 {
799
800 /*
801 * tliSwitchPoint will throw an error if the checkpoint's timeline is
802 * not in expectedTLEs at all.
803 */
806 (errmsg("requested timeline %u is not a child of this server's history",
808 /* translator: %s is a backup_label file or a pg_control file */
809 errdetail("Latest checkpoint in file \"%s\" is at %X/%08X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%08X.",
810 haveBackupLabel ? "backup_label" : "pg_control",
814 }
815
816 /*
817 * The min recovery point should be part of the requested timeline's
818 * history, too.
819 */
824 errmsg("requested timeline %u does not contain minimum recovery point %X/%08X on timeline %u",
828
830 errmsg_internal("redo record is at %X/%08X; shutdown %s",
831 LSN_FORMAT_ARGS(checkPoint.redo),
832 wasShutdown ? "true" : "false"));
834 (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
836 checkPoint.nextOid)));
838 (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %" PRIu64,
839 checkPoint.nextMulti, checkPoint.nextMultiOffset)));
841 (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
842 checkPoint.oldestXid, checkPoint.oldestXidDB)));
844 (errmsg_internal("oldest MultiXactId: %u, in database %u",
845 checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
847 (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
848 checkPoint.oldestCommitTsXid,
849 checkPoint.newestCommitTsXid)));
852 (errmsg("invalid next transaction ID")));
853
854 /* sanity check */
855 if (checkPoint.redo > CheckPointLoc)
857 (errmsg("invalid redo in checkpoint record")));
858
859 /*
860 * Check whether we need to force recovery from WAL. If it appears to
861 * have been a clean shutdown and we did not have a recovery signal file,
862 * then assume no recovery needed.
863 */
864 if (checkPoint.redo < CheckPointLoc)
865 {
866 if (wasShutdown)
868 (errmsg("invalid redo record in shutdown checkpoint")));
869 InRecovery = true;
870 }
871 else if (ControlFile->state != DB_SHUTDOWNED)
872 InRecovery = true;
874 {
875 /* force recovery due to presence of recovery signal file */
876 InRecovery = true;
877 }
878
879 /*
880 * If recovery is needed, update our in-memory copy of pg_control to show
881 * that we are recovering and to show the selected checkpoint as the place
882 * we are starting from. We also mark pg_control with any minimum recovery
883 * stop point obtained from a backup history file.
884 *
885 * We don't write the changes to disk yet, though. Only do that after
886 * initializing various subsystems.
887 */
888 if (InRecovery)
889 {
891 {
893 }
894 else
895 {
896 ereport(LOG,
897 (errmsg("database system was not properly shut down; "
898 "automatic recovery in progress")));
900 ereport(LOG,
901 (errmsg("crash recovery starts in timeline %u "
902 "and has target timeline %u",
906 }
908 ControlFile->checkPointCopy = checkPoint;
910 {
911 /* initialize minRecoveryPoint if not set yet */
912 if (ControlFile->minRecoveryPoint < checkPoint.redo)
913 {
914 ControlFile->minRecoveryPoint = checkPoint.redo;
916 }
917 }
918
919 /*
920 * Set backupStartPoint if we're starting recovery from a base backup.
921 *
922 * Also set backupEndPoint and use minRecoveryPoint as the backup end
923 * location if we're starting recovery from a base backup which was
924 * taken from a standby. In this case, the database system status in
925 * pg_control must indicate that the database was already in recovery.
926 * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
927 * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
928 * before reaching this point; e.g. because restore_command or
929 * primary_conninfo were faulty.
930 *
931 * Any other state indicates that the backup somehow became corrupted
932 * and we can't sensibly continue with recovery.
933 */
934 if (haveBackupLabel)
935 {
936 ControlFile->backupStartPoint = checkPoint.redo;
938
940 {
944 (errmsg("backup_label contains data inconsistent with control file"),
945 errhint("This means that the backup is corrupted and you will "
946 "have to use another backup for recovery.")));
948 }
949 }
950 }
951
952 /* remember these, so that we know when we have reached consistency */
957 {
960 }
961 else
962 {
965 }
966
967 /*
968 * Start recovery assuming that the final record isn't lost.
969 */
972
976}
977
978/*
979 * See if there are any recovery signal files and if so, set state for
980 * recovery.
981 *
982 * See if there is a recovery command file (recovery.conf), and if so
983 * throw an ERROR since as of PG12 we no longer recognize that.
984 */
985static void
987{
988 struct stat stat_buf;
989
991 return;
992
993 /*
994 * Check for old recovery API file: recovery.conf
995 */
999 errmsg("using recovery command file \"%s\" is not supported",
1001
1002 /*
1003 * Remove unused .done file, if present. Ignore if absent.
1004 */
1006
1007 /*
1008 * Check for recovery signal files and if found, fsync them since they
1009 * represent server state information. We don't sweat too much about the
1010 * possibility of fsync failure, however.
1011 */
1012 if (stat(STANDBY_SIGNAL_FILE, &stat_buf) == 0)
1013 {
1014 int fd;
1015
1017 S_IRUSR | S_IWUSR);
1018 if (fd >= 0)
1019 {
1020 (void) pg_fsync(fd);
1021 close(fd);
1022 }
1024 }
1025
1027 {
1028 int fd;
1029
1031 S_IRUSR | S_IWUSR);
1032 if (fd >= 0)
1033 {
1034 (void) pg_fsync(fd);
1035 close(fd);
1036 }
1038 }
1039
1040 /*
1041 * If both signal files are present, standby signal file takes precedence.
1042 * If neither is present then we won't enter archive recovery.
1043 */
1044 StandbyModeRequested = false;
1047 {
1048 StandbyModeRequested = true;
1050 }
1052 {
1053 StandbyModeRequested = false;
1055 }
1056 else
1057 return;
1058
1059 /*
1060 * We don't support standby mode in standalone backends; that requires
1061 * other processes such as the WAL receiver to be alive.
1062 */
1064 ereport(FATAL,
1066 errmsg("standby mode is not supported by single-user servers")));
1067}
1068
1069static void
1071{
1072 /* Reject conflicting targets even when recovery was not requested */
1074
1076 return;
1077
1078 /*
1079 * Check for compulsory parameters
1080 */
1082 {
1083 if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
1086 (errmsg("specified neither \"primary_conninfo\" nor \"restore_command\""),
1087 errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1088 }
1089 else
1090 {
1093 ereport(FATAL,
1095 errmsg("must specify \"restore_command\" when standby mode is not enabled")));
1096 }
1097
1098 /*
1099 * Override any inconsistent requests. Note that this is a change of
1100 * behaviour in 9.5; prior to this we simply ignored a request to pause if
1101 * hot_standby = off, which was surprising behaviour.
1102 */
1106
1107 /*
1108 * Final parsing of recovery_target_time string; see also
1109 * check_recovery_target_time().
1110 */
1112 {
1116 Int32GetDatum(-1)));
1117 }
1118
1119 /*
1120 * If user specified recovery_target_timeline, validate it or compute the
1121 * "latest" value. We can't do this until after we've gotten the restore
1122 * command and set InArchiveRecovery, because we need to fetch timeline
1123 * history files from the archive.
1124 */
1126 {
1128
1129 /* Timeline 1 does not have a history file, all else should */
1130 if (rtli != 1 && !existsTimeLineHistory(rtli))
1131 ereport(FATAL,
1133 errmsg("recovery target timeline %u does not exist",
1134 rtli)));
1136 }
1138 {
1139 /* We start the "latest" search from pg_control's timeline */
1141 }
1142 else
1143 {
1144 /*
1145 * else we just use the recoveryTargetTLI as already read from
1146 * ControlFile
1147 */
1149 }
1150}
1151
1152/*
1153 * read_backup_label: check to see if a backup_label file is present
1154 *
1155 * If we see a backup_label during recovery, we assume that we are recovering
1156 * from a backup dump file, and we therefore roll forward from the checkpoint
1157 * identified by the label file, NOT what pg_control says. This avoids the
1158 * problem that pg_control might have been archived one or more checkpoints
1159 * later than the start of the dump, and so if we rely on it as the start
1160 * point, we will fail to restore a consistent database state.
1161 *
1162 * Returns true if a backup_label was found (and fills the checkpoint
1163 * location and TLI into *checkPointLoc and *backupLabelTLI, respectively);
1164 * returns false if not. If this backup_label came from a streamed backup,
1165 * *backupEndRequired is set to true. If this backup_label was created during
1166 * recovery, *backupFromStandby is set to true.
1167 *
1168 * Also sets the global variables RedoStartLSN and RedoStartTLI with the LSN
1169 * and TLI read from the backup file.
1170 */
1171static bool
1174{
1178 FILE *lfp;
1179 char ch;
1180 char backuptype[20];
1181 char backupfrom[20];
1182 char backuplabel[MAXPGPATH];
1183 char backuptime[128];
1184 uint32 hi,
1185 lo;
1186
1187 /* suppress possible uninitialized-variable warnings */
1189 *backupLabelTLI = 0;
1190 *backupEndRequired = false;
1191 *backupFromStandby = false;
1192
1193 /*
1194 * See if label file is present
1195 */
1197 if (!lfp)
1198 {
1199 if (errno != ENOENT)
1200 ereport(FATAL,
1202 errmsg("could not read file \"%s\": %m",
1204 return false; /* it's not there, all is fine */
1205 }
1206
1207 /*
1208 * Read and parse the START WAL LOCATION and CHECKPOINT lines (this code
1209 * is pretty crude, but we are not expecting any variability in the file
1210 * format).
1211 */
1212 if (fscanf(lfp, "START WAL LOCATION: %X/%08X (file %08X%16s)%c",
1213 &hi, &lo, &tli_from_walseg, startxlogfilename, &ch) != 5 || ch != '\n')
1214 ereport(FATAL,
1216 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
1217 RedoStartLSN = ((uint64) hi) << 32 | lo;
1219 if (fscanf(lfp, "CHECKPOINT LOCATION: %X/%08X%c",
1220 &hi, &lo, &ch) != 3 || ch != '\n')
1221 ereport(FATAL,
1223 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
1224 *checkPointLoc = ((uint64) hi) << 32 | lo;
1226
1227 /*
1228 * BACKUP METHOD lets us know if this was a typical backup ("streamed",
1229 * which could mean either pg_basebackup or the pg_backup_start/stop
1230 * method was used) or if this label came from somewhere else (the only
1231 * other option today being from pg_rewind). If this was a streamed
1232 * backup then we know that we need to play through until we get to the
1233 * end of the WAL which was generated during the backup (at which point we
1234 * will have reached consistency and backupEndRequired will be reset to be
1235 * false).
1236 */
1237 if (fscanf(lfp, "BACKUP METHOD: %19s\n", backuptype) == 1)
1238 {
1239 if (strcmp(backuptype, "streamed") == 0)
1240 *backupEndRequired = true;
1241 }
1242
1243 /*
1244 * BACKUP FROM lets us know if this was from a primary or a standby. If
1245 * it was from a standby, we'll double-check that the control file state
1246 * matches that of a standby.
1247 */
1248 if (fscanf(lfp, "BACKUP FROM: %19s\n", backupfrom) == 1)
1249 {
1250 if (strcmp(backupfrom, "standby") == 0)
1251 *backupFromStandby = true;
1252 }
1253
1254 /*
1255 * Parse START TIME and LABEL. Those are not mandatory fields for recovery
1256 * but checking for their presence is useful for debugging and the next
1257 * sanity checks. Cope also with the fact that the result buffers have a
1258 * pre-allocated size, hence if the backup_label file has been generated
1259 * with strings longer than the maximum assumed here an incorrect parsing
1260 * happens. That's fine as only minor consistency checks are done
1261 * afterwards.
1262 */
1263 if (fscanf(lfp, "START TIME: %127[^\n]\n", backuptime) == 1)
1265 (errmsg_internal("backup time %s in file \"%s\"",
1267
1268 if (fscanf(lfp, "LABEL: %1023[^\n]\n", backuplabel) == 1)
1270 (errmsg_internal("backup label %s in file \"%s\"",
1272
1273 /*
1274 * START TIMELINE is new as of 11. Its parsing is not mandatory, still use
1275 * it as a sanity check if present.
1276 */
1277 if (fscanf(lfp, "START TIMELINE: %u\n", &tli_from_file) == 1)
1278 {
1280 ereport(FATAL,
1282 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE),
1283 errdetail("Timeline ID parsed is %u, but expected %u.",
1285
1287 (errmsg_internal("backup timeline %u in file \"%s\"",
1289 }
1290
1291 if (fscanf(lfp, "INCREMENTAL FROM LSN: %X/%08X\n", &hi, &lo) > 0)
1292 ereport(FATAL,
1294 errmsg("this is an incremental backup, not a data directory"),
1295 errhint("Use pg_combinebackup to reconstruct a valid data directory.")));
1296
1297 if (ferror(lfp) || FreeFile(lfp))
1298 ereport(FATAL,
1300 errmsg("could not read file \"%s\": %m",
1302
1303 return true;
1304}
1305
1306/*
1307 * read_tablespace_map: check to see if a tablespace_map file is present
1308 *
1309 * If we see a tablespace_map file during recovery, we assume that we are
1310 * recovering from a backup dump file, and we therefore need to create symlinks
1311 * as per the information present in tablespace_map file.
1312 *
1313 * Returns true if a tablespace_map file was found (and fills *tablespaces
1314 * with a tablespaceinfo struct for each tablespace listed in the file);
1315 * returns false if not.
1316 */
1317static bool
1319{
1321 FILE *lfp;
1322 char str[MAXPGPATH];
1323 int ch,
1324 i,
1325 n;
1326 bool was_backslash;
1327
1328 /*
1329 * See if tablespace_map file is present
1330 */
1332 if (!lfp)
1333 {
1334 if (errno != ENOENT)
1335 ereport(FATAL,
1337 errmsg("could not read file \"%s\": %m",
1338 TABLESPACE_MAP)));
1339 return false; /* it's not there, all is fine */
1340 }
1341
1342 /*
1343 * Read and parse the link name and path lines from tablespace_map file
1344 * (this code is pretty crude, but we are not expecting any variability in
1345 * the file format). De-escape any backslashes that were inserted.
1346 */
1347 i = 0;
1348 was_backslash = false;
1349 while ((ch = fgetc(lfp)) != EOF)
1350 {
1351 if (!was_backslash && (ch == '\n' || ch == '\r'))
1352 {
1353 char *endp;
1354
1355 if (i == 0)
1356 continue; /* \r immediately followed by \n */
1357
1358 /*
1359 * The de-escaped line should contain an OID followed by exactly
1360 * one space followed by a path. The path might start with
1361 * spaces, so don't be too liberal about parsing.
1362 */
1363 str[i] = '\0';
1364 n = 0;
1365 while (str[n] && str[n] != ' ')
1366 n++;
1367 if (n < 1 || n >= i - 1)
1368 ereport(FATAL,
1370 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1371 str[n++] = '\0';
1372
1374 errno = 0;
1375 ti->oid = strtoul(str, &endp, 10);
1376 if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
1377 ereport(FATAL,
1379 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1380 ti->path = pstrdup(str + n);
1381 *tablespaces = lappend(*tablespaces, ti);
1382
1383 i = 0;
1384 continue;
1385 }
1386 else if (!was_backslash && ch == '\\')
1387 was_backslash = true;
1388 else
1389 {
1390 if (i < sizeof(str) - 1)
1391 str[i++] = ch;
1392 was_backslash = false;
1393 }
1394 }
1395
1396 if (i != 0 || was_backslash) /* last line not terminated? */
1397 ereport(FATAL,
1399 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1400
1401 if (ferror(lfp) || FreeFile(lfp))
1402 ereport(FATAL,
1404 errmsg("could not read file \"%s\": %m",
1405 TABLESPACE_MAP)));
1406
1407 return true;
1408}
1409
1410/*
1411 * Finish WAL recovery.
1412 *
1413 * This does not close the 'xlogreader' yet, because in some cases the caller
1414 * still wants to re-read the last checkpoint record by calling
1415 * ReadCheckpointRecord().
1416 *
1417 * Returns the position of the last valid or applied record, after which new
1418 * WAL should be appended, information about why recovery was ended, and some
1419 * other things. See the EndOfWalRecoveryInfo struct for details.
1420 */
1423{
1425 XLogRecPtr lastRec;
1426 TimeLineID lastRecTLI;
1427 XLogRecPtr endOfLog;
1428
1429 /*
1430 * Kill WAL receiver, if it's still running, before we continue to write
1431 * the startup checkpoint and aborted-contrecord records. It will trump
1432 * over these records and subsequent ones if it's still alive when we
1433 * start writing WAL.
1434 */
1436
1437 /*
1438 * Shutdown the slot sync worker to drop any temporary slots acquired by
1439 * it and to prevent it from keep trying to fetch the failover slots.
1440 *
1441 * We do not update the 'synced' column in 'pg_replication_slots' system
1442 * view from true to false here, as any failed update could leave 'synced'
1443 * column false for some slots. This could cause issues during slot sync
1444 * after restarting the server as a standby. While updating the 'synced'
1445 * column after switching to the new timeline is an option, it does not
1446 * simplify the handling for the 'synced' column. Therefore, we retain the
1447 * 'synced' column as true after promotion as it may provide useful
1448 * information about the slot origin.
1449 */
1451
1452 /*
1453 * We are now done reading the xlog from stream. Turn off streaming
1454 * recovery to force fetching the files (which would be required at end of
1455 * recovery, e.g., timeline history file) from archive or pg_wal.
1456 *
1457 * Note that standby mode must be turned off after killing WAL receiver,
1458 * i.e., calling XLogShutdownWalRcv().
1459 */
1461 StandbyMode = false;
1462
1463 /*
1464 * Determine where to start writing WAL next.
1465 *
1466 * Re-fetch the last valid or last applied record, so we can identify the
1467 * exact endpoint of what we consider the valid portion of WAL. There may
1468 * be an incomplete continuation record after that, in which case
1469 * 'abortedRecPtr' and 'missingContrecPtr' are set and the caller will
1470 * write a special OVERWRITE_CONTRECORD message to mark that the rest of
1471 * it is intentionally missing. See CreateOverwriteContrecordRecord().
1472 *
1473 * An important side-effect of this is to load the last page into
1474 * xlogreader. The caller uses it to initialize the WAL for writing.
1475 */
1476 if (!InRecovery)
1477 {
1478 lastRec = CheckPointLoc;
1479 lastRecTLI = CheckPointTLI;
1480 }
1481 else
1482 {
1484 lastRecTLI = XLogRecoveryCtl->lastReplayedTLI;
1485 }
1487 (void) ReadRecord(xlogprefetcher, PANIC, false, lastRecTLI);
1488 endOfLog = xlogreader->EndRecPtr;
1489
1490 /*
1491 * Remember the TLI in the filename of the XLOG segment containing the
1492 * end-of-log. It could be different from the timeline that endOfLog
1493 * nominally belongs to, if there was a timeline switch in that segment,
1494 * and we were reading the old WAL from a segment belonging to a higher
1495 * timeline.
1496 */
1497 result->endOfLogTLI = xlogreader->seg.ws_tli;
1498
1500 {
1501 /*
1502 * We are no longer in archive recovery state.
1503 *
1504 * We are now done reading the old WAL. Turn off archive fetching if
1505 * it was active.
1506 */
1508 InArchiveRecovery = false;
1509
1510 /*
1511 * If the ending log segment is still open, close it (to avoid
1512 * problems on Windows with trying to rename or delete an open file).
1513 */
1514 if (readFile >= 0)
1515 {
1516 close(readFile);
1517 readFile = -1;
1518 }
1519 }
1520
1521 /*
1522 * Copy the last partial block to the caller, for initializing the WAL
1523 * buffer for appending new WAL.
1524 */
1525 if (endOfLog % XLOG_BLCKSZ != 0)
1526 {
1527 char *page;
1528 int len;
1530
1531 pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1533
1534 /* Copy the valid part of the last block */
1535 len = endOfLog % XLOG_BLCKSZ;
1536 page = palloc(len);
1537 memcpy(page, xlogreader->readBuf, len);
1538
1539 result->lastPageBeginPtr = pageBeginPtr;
1540 result->lastPage = page;
1541 }
1542 else
1543 {
1544 /* There is no partial block to copy. */
1545 result->lastPageBeginPtr = endOfLog;
1546 result->lastPage = NULL;
1547 }
1548
1549 /*
1550 * Create a comment for the history file to explain why and where timeline
1551 * changed.
1552 */
1553 result->recoveryStopReason = getRecoveryStopReason();
1554
1555 result->lastRec = lastRec;
1556 result->lastRecTLI = lastRecTLI;
1557 result->endOfLog = endOfLog;
1558
1559 result->abortedRecPtr = abortedRecPtr;
1560 result->missingContrecPtr = missingContrecPtr;
1561
1562 result->standby_signal_file_found = standby_signal_file_found;
1563 result->recovery_signal_file_found = recovery_signal_file_found;
1564
1565 return result;
1566}
1567
1568/*
1569 * Clean up the WAL reader and leftovers from restoring WAL from archive
1570 */
1571void
1573{
1574 char recoveryPath[MAXPGPATH];
1575
1576 /* Final update of pg_stat_recovery_prefetch. */
1578
1579 /* Shut down xlogreader */
1580 if (readFile >= 0)
1581 {
1582 close(readFile);
1583 readFile = -1;
1584 }
1588
1590 {
1591 /*
1592 * Since there might be a partial WAL segment named RECOVERYXLOG, get
1593 * rid of it.
1594 */
1595 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1596 unlink(recoveryPath); /* ignore any error */
1597
1598 /* Get rid of any remaining recovered timeline-history file, too */
1599 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1600 unlink(recoveryPath); /* ignore any error */
1601 }
1602
1603 /*
1604 * We don't need the latch anymore. It's not strictly necessary to disown
1605 * it, but let's do it for the sake of tidiness.
1606 */
1609}
1610
1611/*
1612 * Perform WAL recovery.
1613 *
1614 * If the system was shut down cleanly, this is never called.
1615 */
1616void
1618{
1619 XLogRecord *record;
1620 bool reachedRecoveryTarget = false;
1621 TimeLineID replayTLI;
1622
1623 /*
1624 * Initialize shared variables for tracking progress of WAL replay, as if
1625 * we had just replayed the record before the REDO location (or the
1626 * checkpoint record itself, if it's a shutdown checkpoint).
1627 */
1630 {
1634 }
1635 else
1636 {
1640 }
1647
1648 /* Also ensure XLogReceiptTime has a sane value */
1650
1651 /*
1652 * Let postmaster know we've started redo now, so that it can launch the
1653 * archiver if necessary.
1654 */
1657
1658 /*
1659 * Allow read-only connections immediately if we're consistent already.
1660 */
1662
1663 /*
1664 * Find the first record that logically follows the checkpoint --- it
1665 * might physically precede it, though.
1666 */
1668 {
1669 /* back up to find the record */
1670 replayTLI = RedoStartTLI;
1672 record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1673
1674 /*
1675 * If a checkpoint record's redo pointer points back to an earlier
1676 * LSN, the record at that LSN should be an XLOG_CHECKPOINT_REDO
1677 * record.
1678 */
1679 if (record->xl_rmid != RM_XLOG_ID ||
1681 ereport(FATAL,
1682 errmsg("unexpected record type found at redo point %X/%08X",
1684 }
1685 else
1686 {
1687 /* just have to read next record after CheckPoint */
1689 replayTLI = CheckPointTLI;
1690 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1691 }
1692
1693 if (record != NULL)
1694 {
1696 PGRUsage ru0;
1697
1699
1700 InRedo = true;
1701
1702 RmgrStartup();
1703
1704 ereport(LOG,
1705 errmsg("redo starts at %X/%08X",
1707
1708 /* Prepare to report progress of the redo phase. */
1709 if (!StandbyMode)
1711
1712 /*
1713 * main redo apply loop
1714 */
1715 do
1716 {
1717 if (!StandbyMode)
1718 ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%08X",
1720
1721#ifdef WAL_DEBUG
1722 if (XLOG_DEBUG)
1723 {
1725
1727 appendStringInfo(&buf, "REDO @ %X/%08X; LSN %X/%08X: ",
1731 appendStringInfoString(&buf, " - ");
1733 elog(LOG, "%s", buf.data);
1734 pfree(buf.data);
1735 }
1736#endif
1737
1738 /* Handle interrupt signals of startup process */
1740
1741 /*
1742 * Pause WAL replay, if requested by a hot-standby session via
1743 * SetRecoveryPause().
1744 *
1745 * Note that we intentionally don't take the info_lck spinlock
1746 * here. We might therefore read a slightly stale value of the
1747 * recoveryPause flag, but it can't be very stale (no worse than
1748 * the last spinlock we did acquire). Since a pause request is a
1749 * pretty asynchronous thing anyway, possibly responding to it one
1750 * WAL record later than we otherwise would is a minor issue, so
1751 * it doesn't seem worth adding another spinlock cycle to prevent
1752 * that.
1753 */
1754 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1756 recoveryPausesHere(false);
1757
1758 /*
1759 * Have we reached our recovery target?
1760 */
1762 {
1763 reachedRecoveryTarget = true;
1764 break;
1765 }
1766
1767 /*
1768 * If we've been asked to lag the primary, wait on latch until
1769 * enough time has passed.
1770 */
1772 {
1773 /*
1774 * We test for paused recovery again here. If user sets
1775 * delayed apply, it may be because they expect to pause
1776 * recovery in case of problems, so we must test again here
1777 * otherwise pausing during the delay-wait wouldn't work.
1778 */
1779 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1781 recoveryPausesHere(false);
1782 }
1783
1784 /*
1785 * Apply the record
1786 */
1787 ApplyWalRecord(xlogreader, record, &replayTLI);
1788
1789 /*
1790 * Wake up processes waiting for standby replay, write, or flush
1791 * LSN to reach current replay position. Replay implies that the
1792 * WAL was already written and flushed to disk, so write and flush
1793 * waiters can be woken at the replay position too.
1794 */
1801
1802 /* Exit loop if we reached inclusive recovery target */
1804 {
1805 reachedRecoveryTarget = true;
1806 break;
1807 }
1808
1809 /* Else, try to fetch the next WAL record */
1810 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1811 } while (record != NULL);
1812
1813 /*
1814 * end of main redo apply loop
1815 */
1816
1818 {
1819 if (!reachedConsistency)
1820 ereport(FATAL,
1821 (errmsg("requested recovery stop point is before consistent recovery point")));
1822
1823 /*
1824 * This is the last point where we can restart recovery with a new
1825 * recovery target, if we shutdown and begin again. After this,
1826 * Resource Managers may choose to do permanent corrective actions
1827 * at end of recovery.
1828 */
1829 switch (recoveryTargetAction)
1830 {
1832
1833 /*
1834 * exit with special return code to request shutdown of
1835 * postmaster. Log messages issued from postmaster.
1836 */
1837 proc_exit(3);
1838
1840 SetRecoveryPause(true);
1841 recoveryPausesHere(true);
1842
1843 /* drop into promote */
1845
1847 break;
1848 }
1849 }
1850
1851 RmgrCleanup();
1852
1853 ereport(LOG,
1854 errmsg("redo done at %X/%08X system usage: %s",
1856 pg_rusage_show(&ru0)));
1858 if (xtime)
1859 ereport(LOG,
1860 (errmsg("last completed transaction was at log time %s",
1862
1863 InRedo = false;
1864 }
1865 else
1866 {
1867 /* there are no WAL records following the checkpoint */
1868 ereport(LOG,
1869 (errmsg("redo is not required")));
1870 }
1871
1872 /*
1873 * This check is intentionally after the above log messages that indicate
1874 * how far recovery went.
1875 */
1879 ereport(FATAL,
1881 errmsg("recovery ended before configured recovery target was reached")));
1882}
1883
1884/*
1885 * Subroutine of PerformWalRecovery, to apply one WAL record.
1886 */
1887static void
1889{
1890 ErrorContextCallback errcallback;
1891 bool switchedTLI = false;
1892
1893 /* Setup error traceback support for ereport() */
1894 errcallback.callback = rm_redo_error_callback;
1895 errcallback.arg = xlogreader;
1896 errcallback.previous = error_context_stack;
1897 error_context_stack = &errcallback;
1898
1899 /*
1900 * TransamVariables->nextXid must be beyond record's xid.
1901 */
1903
1904 /*
1905 * Before replaying this record, check if this record causes the current
1906 * timeline to change. The record is already considered to be part of the
1907 * new timeline, so we update replayTLI before replaying it. That's
1908 * important so that replayEndTLI, which is recorded as the minimum
1909 * recovery point's TLI if recovery stops after this record, is set
1910 * correctly.
1911 */
1912 if (record->xl_rmid == RM_XLOG_ID)
1913 {
1914 TimeLineID newReplayTLI = *replayTLI;
1915 TimeLineID prevReplayTLI = *replayTLI;
1916 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1917
1918 if (info == XLOG_CHECKPOINT_SHUTDOWN)
1919 {
1920 CheckPoint checkPoint;
1921
1922 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
1923 newReplayTLI = checkPoint.ThisTimeLineID;
1924 prevReplayTLI = checkPoint.PrevTimeLineID;
1925 }
1926 else if (info == XLOG_END_OF_RECOVERY)
1927 {
1929
1931 newReplayTLI = xlrec.ThisTimeLineID;
1932 prevReplayTLI = xlrec.PrevTimeLineID;
1933 }
1934
1935 if (newReplayTLI != *replayTLI)
1936 {
1937 /* Check that it's OK to switch to this TLI */
1939 newReplayTLI, prevReplayTLI, *replayTLI);
1940
1941 /* Following WAL records should be run with new TLI */
1942 *replayTLI = newReplayTLI;
1943 switchedTLI = true;
1944 }
1945 }
1946
1947 /*
1948 * Update shared replayEndRecPtr before replaying this record, so that
1949 * XLogFlush will update minRecoveryPoint correctly.
1950 */
1953 XLogRecoveryCtl->replayEndTLI = *replayTLI;
1955
1956 /*
1957 * If we are attempting to enter Hot Standby mode, process XIDs we see
1958 */
1962
1963 /*
1964 * Some XLOG record types that are related to recovery are processed
1965 * directly here, rather than in xlog_redo()
1966 */
1967 if (record->xl_rmid == RM_XLOG_ID)
1968 xlogrecovery_redo(xlogreader, *replayTLI);
1969
1970 /* Now apply the WAL record itself */
1972
1973 /*
1974 * After redo, check whether the backup pages associated with the WAL
1975 * record are consistent with the existing pages. This check is done only
1976 * if consistency check is enabled for this record.
1977 */
1978 if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
1980
1981 /* Pop the error context stack */
1982 error_context_stack = errcallback.previous;
1983
1984 /*
1985 * Update lastReplayedEndRecPtr after this record has been successfully
1986 * replayed.
1987 */
1991 XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
1993
1994 /* ------
1995 * Wakeup walsenders:
1996 *
1997 * On the standby, the WAL is flushed first (which will only wake up
1998 * physical walsenders) and then applied, which will only wake up logical
1999 * walsenders.
2000 *
2001 * Indeed, logical walsenders on standby can't decode and send data until
2002 * it's been applied.
2003 *
2004 * Physical walsenders don't need to be woken up during replay unless
2005 * cascading replication is allowed and time line change occurred (so that
2006 * they can notice that they are on a new time line).
2007 *
2008 * That's why the wake up conditions are for:
2009 *
2010 * - physical walsenders in case of new time line and cascade
2011 * replication is allowed
2012 * - logical walsenders in case cascade replication is allowed (could not
2013 * be created otherwise)
2014 * ------
2015 */
2018
2019 /*
2020 * If rm_redo called XLogRequestWalReceiverReply, then we wake up the
2021 * receiver so that it notices the updated lastReplayedEndRecPtr and sends
2022 * a reply to the primary.
2023 */
2025 {
2028 }
2029
2030 /* Allow read-only connections if we're consistent now */
2032
2033 /* Is this a timeline switch? */
2034 if (switchedTLI)
2035 {
2036 /*
2037 * Before we continue on the new timeline, clean up any (possibly
2038 * bogus) future WAL segments on the old timeline.
2039 */
2041
2042 /* Reset the prefetcher. */
2044 }
2045}
2046
2047/*
2048 * Some XLOG RM record types that are directly related to WAL recovery are
2049 * handled here rather than in the xlog_redo()
2050 */
2051static void
2053{
2054 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2055 XLogRecPtr lsn = record->EndRecPtr;
2056
2057 Assert(XLogRecGetRmid(record) == RM_XLOG_ID);
2058
2059 if (info == XLOG_OVERWRITE_CONTRECORD)
2060 {
2061 /* Verify the payload of a XLOG_OVERWRITE_CONTRECORD record. */
2063
2065 if (xlrec.overwritten_lsn != record->overwrittenRecPtr)
2066 elog(FATAL, "mismatching overwritten LSN %X/%08X -> %X/%08X",
2067 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
2069
2070 /* We have safely skipped the aborted record */
2073
2074 ereport(LOG,
2075 errmsg("successfully skipped missing contrecord at %X/%08X, overwritten at %s",
2076 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
2077 timestamptz_to_str(xlrec.overwrite_time)));
2078
2079 /* Verifying the record should only happen once */
2081 }
2082 else if (info == XLOG_BACKUP_END)
2083 {
2084 XLogRecPtr startpoint;
2085
2086 memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
2087
2088 if (backupStartPoint == startpoint)
2089 {
2090 /*
2091 * We have reached the end of base backup, the point where
2092 * pg_backup_stop() was done. The data on disk is now consistent
2093 * (assuming we have also reached minRecoveryPoint). Set
2094 * backupEndPoint to the current LSN, so that the next call to
2095 * CheckRecoveryConsistency() will notice it and do the
2096 * end-of-backup processing.
2097 */
2098 elog(DEBUG1, "end of backup record reached");
2099
2100 backupEndPoint = lsn;
2101 }
2102 else
2103 elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%08X, waiting for %X/%08X",
2105 }
2106}
2107
2108/*
2109 * Verify that, in non-test mode, ./pg_tblspc doesn't contain any real
2110 * directories.
2111 *
2112 * Replay of database creation XLOG records for databases that were later
2113 * dropped can create fake directories in pg_tblspc. By the time consistency
2114 * is reached these directories should have been removed; here we verify
2115 * that this did indeed happen. This is to be called at the point where
2116 * consistent state is reached.
2117 *
2118 * allow_in_place_tablespaces turns the PANIC into a WARNING, which is
2119 * useful for testing purposes, and also allows for an escape hatch in case
2120 * things go south.
2121 */
2122static void
2124{
2125 DIR *dir;
2126 struct dirent *de;
2127
2129 while ((de = ReadDir(dir, PG_TBLSPC_DIR)) != NULL)
2130 {
2131 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR)];
2132
2133 /* Skip entries of non-oid names */
2134 if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
2135 continue;
2136
2137 snprintf(path, sizeof(path), "%s/%s", PG_TBLSPC_DIR, de->d_name);
2138
2139 if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
2142 errmsg("unexpected directory entry \"%s\" found in %s",
2143 de->d_name, PG_TBLSPC_DIR),
2144 errdetail("All directory entries in %s/ should be symbolic links.",
2146 errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
2147 }
2148}
2149
2150/*
2151 * Checks if recovery has reached a consistent state. When consistency is
2152 * reached and we have a valid starting standby snapshot, tell postmaster
2153 * that it can start accepting read-only connections.
2154 */
2155static void
2157{
2158 XLogRecPtr lastReplayedEndRecPtr;
2159 TimeLineID lastReplayedTLI;
2160
2161 /*
2162 * During crash recovery, we don't reach a consistent state until we've
2163 * replayed all the WAL.
2164 */
2166 return;
2167
2169
2170 /*
2171 * assume that we are called in the startup process, and hence don't need
2172 * a lock to read lastReplayedEndRecPtr
2173 */
2174 lastReplayedEndRecPtr = XLogRecoveryCtl->lastReplayedEndRecPtr;
2175 lastReplayedTLI = XLogRecoveryCtl->lastReplayedTLI;
2176
2177 /*
2178 * Have we reached the point where our base backup was completed?
2179 */
2181 backupEndPoint <= lastReplayedEndRecPtr)
2182 {
2185
2186 elog(DEBUG1, "end of backup reached");
2187
2188 /*
2189 * We have reached the end of base backup, as indicated by pg_control.
2190 * Update the control file accordingly.
2191 */
2192 ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI);
2195 backupEndRequired = false;
2196
2197 ereport(LOG,
2198 errmsg("completed backup recovery with redo LSN %X/%08X and end LSN %X/%08X",
2201 }
2202
2203 /*
2204 * Have we passed our safe starting point? Note that minRecoveryPoint is
2205 * known to be incorrectly set if recovering from a backup, until the
2206 * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint.
2207 * All we know prior to that is that we're not consistent yet.
2208 */
2210 minRecoveryPoint <= lastReplayedEndRecPtr)
2211 {
2212 /*
2213 * Check to see if the XLOG sequence contained any unresolved
2214 * references to uninitialized pages.
2215 */
2217
2218 /*
2219 * Check that pg_tblspc doesn't contain any real directories. Replay
2220 * of Database/CREATE_* records may have created fictitious tablespace
2221 * directories that should have been removed by the time consistency
2222 * was reached.
2223 */
2225
2226 reachedConsistency = true;
2228 ereport(LOG,
2229 errmsg("consistent recovery state reached at %X/%08X",
2230 LSN_FORMAT_ARGS(lastReplayedEndRecPtr)));
2231 }
2232
2233 /*
2234 * Have we got a valid starting snapshot that will allow queries to be
2235 * run? If so, we can tell postmaster that the database is consistent now,
2236 * enabling connections.
2237 */
2242 {
2246
2247 LocalHotStandbyActive = true;
2248
2250 }
2251}
2252
2253/*
2254 * Error context callback for errors occurring during rm_redo().
2255 */
2256static void
2258{
2259 XLogReaderState *record = (XLogReaderState *) arg;
2261
2263 xlog_outdesc(&buf, record);
2264 xlog_block_info(&buf, record);
2265
2266 /* translator: %s is a WAL record description */
2267 errcontext("WAL redo at %X/%08X for %s",
2268 LSN_FORMAT_ARGS(record->ReadRecPtr),
2269 buf.data);
2270
2271 pfree(buf.data);
2272}
2273
2274/*
2275 * Returns a string describing an XLogRecord, consisting of its identity
2276 * optionally followed by a colon, a space, and a further description.
2277 */
2278void
2280{
2282 uint8 info = XLogRecGetInfo(record);
2283 const char *id;
2284
2287
2288 id = rmgr.rm_identify(info);
2289 if (id == NULL)
2290 appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2291 else
2292 appendStringInfo(buf, "%s: ", id);
2293
2294 rmgr.rm_desc(buf, record);
2295}
2296
2297#ifdef WAL_DEBUG
2298
2299static void
2301{
2302 appendStringInfo(buf, "prev %X/%08X; xid %u",
2304 XLogRecGetXid(record));
2305
2306 appendStringInfo(buf, "; len %u",
2307 XLogRecGetDataLen(record));
2308
2309 xlog_block_info(buf, record);
2310}
2311#endif /* WAL_DEBUG */
2312
2313/*
2314 * Returns a string giving information about all the blocks in an
2315 * XLogRecord.
2316 */
2317static void
2319{
2320 int block_id;
2321
2322 /* decode block references */
2323 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2324 {
2325 RelFileLocator rlocator;
2326 ForkNumber forknum;
2328
2330 &rlocator, &forknum, &blk, NULL))
2331 continue;
2332
2333 if (forknum != MAIN_FORKNUM)
2334 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, fork %u, blk %u",
2335 block_id,
2336 rlocator.spcOid, rlocator.dbOid,
2337 rlocator.relNumber,
2338 forknum,
2339 blk);
2340 else
2341 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, blk %u",
2342 block_id,
2343 rlocator.spcOid, rlocator.dbOid,
2344 rlocator.relNumber,
2345 blk);
2346 if (XLogRecHasBlockImage(record, block_id))
2347 appendStringInfoString(buf, " FPW");
2348 }
2349}
2350
2351
2352/*
2353 * Check that it's OK to switch to new timeline during recovery.
2354 *
2355 * 'lsn' is the address of the shutdown checkpoint record we're about to
2356 * replay. (Currently, timeline can only change at a shutdown checkpoint).
2357 */
2358static void
2360 TimeLineID replayTLI)
2361{
2362 /* Check that the record agrees on what the current (old) timeline is */
2363 if (prevTLI != replayTLI)
2364 ereport(PANIC,
2365 (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2366 prevTLI, replayTLI)));
2367
2368 /*
2369 * The new timeline better be in the list of timelines we expect to see,
2370 * according to the timeline history. It should also not decrease.
2371 */
2372 if (newTLI < replayTLI || !tliInHistory(newTLI, expectedTLEs))
2373 ereport(PANIC,
2374 (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
2375 newTLI, replayTLI)));
2376
2377 /*
2378 * If we have not yet reached min recovery point, and we're about to
2379 * switch to a timeline greater than the timeline of the min recovery
2380 * point: trouble. After switching to the new timeline, we could not
2381 * possibly visit the min recovery point on the correct timeline anymore.
2382 * This can happen if there is a newer timeline in the archive that
2383 * branched before the timeline the min recovery point is on, and you
2384 * attempt to do PITR to the new timeline.
2385 */
2387 lsn < minRecoveryPoint &&
2389 ereport(PANIC,
2390 errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%08X on timeline %u",
2391 newTLI,
2394
2395 /* Looks good */
2396}
2397
2398
2399/*
2400 * Extract timestamp from WAL record.
2401 *
2402 * If the record contains a timestamp, returns true, and saves the timestamp
2403 * in *recordXtime. If the record type has no timestamp, returns false.
2404 * Currently, only transaction commit/abort records and restore points contain
2405 * timestamps.
2406 */
2407static bool
2409{
2410 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2412 uint8 rmid = XLogRecGetRmid(record);
2413
2414 if (rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2415 {
2416 *recordXtime = ((xl_restore_point *) XLogRecGetData(record))->rp_time;
2417 return true;
2418 }
2419 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_COMMIT ||
2421 {
2422 *recordXtime = ((xl_xact_commit *) XLogRecGetData(record))->xact_time;
2423 return true;
2424 }
2425 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_ABORT ||
2427 {
2428 *recordXtime = ((xl_xact_abort *) XLogRecGetData(record))->xact_time;
2429 return true;
2430 }
2431 return false;
2432}
2433
2434/*
2435 * Checks whether the current buffer page and backup page stored in the
2436 * WAL record are consistent or not. Before comparing the two pages, a
2437 * masking can be applied to the pages to ignore certain areas like hint bits,
2438 * unused space between pd_lower and pd_upper among other things. This
2439 * function should be called once WAL replay has been completed for a
2440 * given record.
2441 */
2442static void
2444{
2446 RelFileLocator rlocator;
2447 ForkNumber forknum;
2448 BlockNumber blkno;
2449 int block_id;
2450
2451 /* Records with no backup blocks have no need for consistency checks. */
2452 if (!XLogRecHasAnyBlockRefs(record))
2453 return;
2454
2456
2457 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2458 {
2459 Buffer buf;
2460 Page page;
2461
2463 &rlocator, &forknum, &blkno, NULL))
2464 {
2465 /*
2466 * WAL record doesn't contain a block reference with the given id.
2467 * Do nothing.
2468 */
2469 continue;
2470 }
2471
2473
2474 if (XLogRecBlockImageApply(record, block_id))
2475 {
2476 /*
2477 * WAL record has already applied the page, so bypass the
2478 * consistency check as that would result in comparing the full
2479 * page stored in the record with itself.
2480 */
2481 continue;
2482 }
2483
2484 /*
2485 * Read the contents from the current buffer and store it in a
2486 * temporary page.
2487 */
2488 buf = XLogReadBufferExtended(rlocator, forknum, blkno,
2491 if (!BufferIsValid(buf))
2492 continue;
2493
2495 page = BufferGetPage(buf);
2496
2497 /*
2498 * Take a copy of the local page where WAL has been applied to have a
2499 * comparison base before masking it...
2500 */
2502
2503 /* No need for this page anymore now that a copy is in. */
2505
2506 /*
2507 * If the block LSN is already ahead of this WAL record, we can't
2508 * expect contents to match. This can happen if recovery is
2509 * restarted.
2510 */
2512 continue;
2513
2514 /*
2515 * Read the contents from the backup copy, stored in WAL record and
2516 * store it in a temporary page. There is no need to allocate a new
2517 * page here, a local buffer is fine to hold its contents and a mask
2518 * can be directly applied on it.
2519 */
2521 ereport(ERROR,
2523 errmsg_internal("%s", record->errormsg_buf)));
2524
2525 /*
2526 * If masking function is defined, mask both the primary and replay
2527 * images
2528 */
2529 if (rmgr.rm_mask != NULL)
2530 {
2531 rmgr.rm_mask(replay_image_masked, blkno);
2532 rmgr.rm_mask(primary_image_masked, blkno);
2533 }
2534
2535 /* Time to compare the primary and replay images. */
2537 {
2538 elog(FATAL,
2539 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2540 rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
2541 forknum, blkno);
2542 }
2543 }
2544}
2545
2546/*
2547 * For point-in-time recovery, this function decides whether we want to
2548 * stop applying the XLOG before the current record.
2549 *
2550 * Returns true if we are stopping, false otherwise. If stopping, some
2551 * information is saved in recoveryStopXid et al for use in annotating the
2552 * new timeline's history file.
2553 */
2554static bool
2556{
2557 bool stopsHere = false;
2559 bool isCommit;
2562
2563 /*
2564 * Ignore recovery target settings when not in archive recovery (meaning
2565 * we are in crash recovery).
2566 */
2568 return false;
2569
2570 /* Check if we should stop as soon as reaching consistency */
2572 {
2573 ereport(LOG,
2574 (errmsg("recovery stopping after reaching consistency")));
2575
2576 recoveryStopAfter = false;
2579 recoveryStopTime = 0;
2580 recoveryStopName[0] = '\0';
2581 return true;
2582 }
2583
2584 /* Check if target LSN has been reached */
2587 record->ReadRecPtr >= recoveryTargetLSN)
2588 {
2589 recoveryStopAfter = false;
2591 recoveryStopLSN = record->ReadRecPtr;
2592 recoveryStopTime = 0;
2593 recoveryStopName[0] = '\0';
2594 ereport(LOG,
2595 errmsg("recovery stopping before WAL location (LSN) \"%X/%08X\"",
2597 return true;
2598 }
2599
2600 /* Otherwise we only consider stopping before COMMIT or ABORT records. */
2601 if (XLogRecGetRmid(record) != RM_XACT_ID)
2602 return false;
2603
2605
2607 {
2608 isCommit = true;
2609 recordXid = XLogRecGetXid(record);
2610 }
2612 {
2615
2616 isCommit = true;
2618 xlrec,
2619 &parsed);
2620 recordXid = parsed.twophase_xid;
2621 }
2622 else if (xact_info == XLOG_XACT_ABORT)
2623 {
2624 isCommit = false;
2625 recordXid = XLogRecGetXid(record);
2626 }
2628 {
2631
2632 isCommit = false;
2634 xlrec,
2635 &parsed);
2636 recordXid = parsed.twophase_xid;
2637 }
2638 else
2639 return false;
2640
2642 {
2643 /*
2644 * There can be only one transaction end record with this exact
2645 * transactionid
2646 *
2647 * when testing for an xid, we MUST test for equality only, since
2648 * transactions are numbered in the order they start, not the order
2649 * they complete. A higher numbered xid will complete before you about
2650 * 50% of the time...
2651 */
2653 }
2654
2655 /*
2656 * Note: we must fetch recordXtime regardless of recoveryTarget setting.
2657 * We don't expect getRecordTimestamp ever to fail, since we already know
2658 * this is a commit or abort record; but test its result anyway.
2659 */
2660 if (getRecordTimestamp(record, &recordXtime) &&
2662 {
2663 /*
2664 * There can be many transactions that share the same commit time, so
2665 * we stop after the last one, if we are inclusive, or stop at the
2666 * first one if we are exclusive
2667 */
2670 else
2672 }
2673
2674 if (stopsHere)
2675 {
2676 recoveryStopAfter = false;
2680 recoveryStopName[0] = '\0';
2681
2682 if (isCommit)
2683 {
2684 ereport(LOG,
2685 (errmsg("recovery stopping before commit of transaction %u, time %s",
2688 }
2689 else
2690 {
2691 ereport(LOG,
2692 (errmsg("recovery stopping before abort of transaction %u, time %s",
2695 }
2696 }
2697
2698 return stopsHere;
2699}
2700
2701/*
2702 * Same as recoveryStopsBefore, but called after applying the record.
2703 *
2704 * We also track the timestamp of the latest applied COMMIT/ABORT
2705 * record in XLogRecoveryCtl->recoveryLastXTime.
2706 */
2707static bool
2709{
2710 uint8 info;
2712 uint8 rmid;
2714
2715 /*
2716 * Ignore recovery target settings when not in archive recovery (meaning
2717 * we are in crash recovery).
2718 */
2720 return false;
2721
2722 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2723 rmid = XLogRecGetRmid(record);
2724
2725 /*
2726 * There can be many restore points that share the same name; we stop at
2727 * the first one.
2728 */
2730 rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2731 {
2733
2735
2737 {
2738 recoveryStopAfter = true;
2743
2744 ereport(LOG,
2745 (errmsg("recovery stopping at restore point \"%s\", time %s",
2748 return true;
2749 }
2750 }
2751
2752 /* Check if the target LSN has been reached */
2755 record->ReadRecPtr >= recoveryTargetLSN)
2756 {
2757 recoveryStopAfter = true;
2759 recoveryStopLSN = record->ReadRecPtr;
2760 recoveryStopTime = 0;
2761 recoveryStopName[0] = '\0';
2762 ereport(LOG,
2763 errmsg("recovery stopping after WAL location (LSN) \"%X/%08X\"",
2765 return true;
2766 }
2767
2768 if (rmid != RM_XACT_ID)
2769 return false;
2770
2771 xact_info = info & XLOG_XACT_OPMASK;
2772
2773 if (xact_info == XLOG_XACT_COMMIT ||
2777 {
2779
2780 /* Update the last applied transaction timestamp */
2781 if (getRecordTimestamp(record, &recordXtime))
2783
2784 /* Extract the XID of the committed/aborted transaction */
2786 {
2789
2791 xlrec,
2792 &parsed);
2793 recordXid = parsed.twophase_xid;
2794 }
2796 {
2799
2801 xlrec,
2802 &parsed);
2803 recordXid = parsed.twophase_xid;
2804 }
2805 else
2806 recordXid = XLogRecGetXid(record);
2807
2808 /*
2809 * There can be only one transaction end record with this exact
2810 * transactionid
2811 *
2812 * when testing for an xid, we MUST test for equality only, since
2813 * transactions are numbered in the order they start, not the order
2814 * they complete. A higher numbered xid will complete before you about
2815 * 50% of the time...
2816 */
2819 {
2820 recoveryStopAfter = true;
2824 recoveryStopName[0] = '\0';
2825
2826 if (xact_info == XLOG_XACT_COMMIT ||
2828 {
2829 ereport(LOG,
2830 (errmsg("recovery stopping after commit of transaction %u, time %s",
2833 }
2834 else if (xact_info == XLOG_XACT_ABORT ||
2836 {
2837 ereport(LOG,
2838 (errmsg("recovery stopping after abort of transaction %u, time %s",
2841 }
2842 return true;
2843 }
2844 }
2845
2846 /* Check if we should stop as soon as reaching consistency */
2848 {
2849 ereport(LOG,
2850 (errmsg("recovery stopping after reaching consistency")));
2851
2852 recoveryStopAfter = true;
2854 recoveryStopTime = 0;
2856 recoveryStopName[0] = '\0';
2857 return true;
2858 }
2859
2860 return false;
2861}
2862
2863/*
2864 * Create a comment for the history file to explain why and where
2865 * timeline changed.
2866 */
2867static char *
2869{
2870 char reason[200];
2871
2873 snprintf(reason, sizeof(reason),
2874 "%s transaction %u",
2875 recoveryStopAfter ? "after" : "before",
2878 snprintf(reason, sizeof(reason),
2879 "%s %s\n",
2880 recoveryStopAfter ? "after" : "before",
2883 snprintf(reason, sizeof(reason),
2884 "%s LSN %X/%08X\n",
2885 recoveryStopAfter ? "after" : "before",
2888 snprintf(reason, sizeof(reason),
2889 "at restore point \"%s\"",
2892 snprintf(reason, sizeof(reason), "reached consistency");
2893 else
2894 snprintf(reason, sizeof(reason), "no recovery target specified");
2895
2896 return pstrdup(reason);
2897}
2898
2899/*
2900 * Wait until shared recoveryPauseState is set to RECOVERY_NOT_PAUSED.
2901 *
2902 * endOfRecovery is true if the recovery target is reached and
2903 * the paused state starts at the end of recovery because of
2904 * recovery_target_action=pause, and false otherwise.
2905 */
2906static void
2908{
2909 /* Don't pause unless users can connect! */
2911 return;
2912
2913 /* Don't pause after standby promotion has been triggered */
2915 return;
2916
2917 if (endOfRecovery)
2918 ereport(LOG,
2919 (errmsg("pausing at the end of recovery"),
2920 errhint("Execute pg_wal_replay_resume() to promote.")));
2921 else
2922 ereport(LOG,
2923 (errmsg("recovery has paused"),
2924 errhint("Execute pg_wal_replay_resume() to continue.")));
2925
2926 /* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */
2928 {
2931 return;
2932
2933 /*
2934 * If recovery pause is requested then set it paused. While we are in
2935 * the loop, user might resume and pause again so set this every time.
2936 */
2938
2939 /*
2940 * We wait on a condition variable that will wake us as soon as the
2941 * pause ends, but we use a timeout so we can check the above exit
2942 * condition periodically too.
2943 */
2946 }
2948}
2949
2950/*
2951 * When recovery_min_apply_delay is set, we wait long enough to make sure
2952 * certain record types are applied at least that interval behind the primary.
2953 *
2954 * Returns true if we waited.
2955 *
2956 * Note that the delay is calculated between the WAL record log time and
2957 * the current time on standby. We would prefer to keep track of when this
2958 * standby received each WAL record, which would allow a more consistent
2959 * approach and one not affected by time synchronisation issues, but that
2960 * is significantly more effort and complexity for little actual gain in
2961 * usability.
2962 */
2963static bool
2965{
2969 long msecs;
2970
2971 /* nothing to do if no delay configured */
2972 if (recovery_min_apply_delay <= 0)
2973 return false;
2974
2975 /* no delay is applied on a database not yet consistent */
2976 if (!reachedConsistency)
2977 return false;
2978
2979 /* nothing to do if crash recovery is requested */
2981 return false;
2982
2983 /*
2984 * Is it a COMMIT record?
2985 *
2986 * We deliberately choose not to delay aborts since they have no effect on
2987 * MVCC. We already allow replay of records that don't have a timestamp,
2988 * so there is already opportunity for issues caused by early conflicts on
2989 * standbys.
2990 */
2991 if (XLogRecGetRmid(record) != RM_XACT_ID)
2992 return false;
2993
2995
2996 if (xact_info != XLOG_XACT_COMMIT &&
2998 return false;
2999
3000 if (!getRecordTimestamp(record, &xtime))
3001 return false;
3002
3004
3005 /*
3006 * Exit without arming the latch if it's already past time to apply this
3007 * record
3008 */
3010 if (msecs <= 0)
3011 return false;
3012
3013 while (true)
3014 {
3016
3017 /* This might change recovery_min_apply_delay. */
3019
3021 break;
3022
3023 /*
3024 * Recalculate delayUntil as recovery_min_apply_delay could have
3025 * changed while waiting in this loop.
3026 */
3028
3029 /*
3030 * Wait for difference between GetCurrentTimestamp() and delayUntil.
3031 */
3033 delayUntil);
3034
3035 if (msecs <= 0)
3036 break;
3037
3038 elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs);
3039
3042 msecs,
3044 }
3045 return true;
3046}
3047
3048/*
3049 * Get the current state of the recovery pause request.
3050 */
3062
3063/*
3064 * Set the recovery pause state.
3065 *
3066 * If recovery pause is requested then sets the recovery pause state to
3067 * 'pause requested' if it is not already 'paused'. Otherwise, sets it
3068 * to 'not paused' to resume the recovery. The recovery pause will be
3069 * confirmed by the ConfirmRecoveryPaused.
3070 */
3071void
3086
3087/*
3088 * Confirm the recovery pause by setting the recovery pause state to
3089 * RECOVERY_PAUSED.
3090 */
3091static void
3100
3101
3102/*
3103 * Attempt to read the next XLOG record.
3104 *
3105 * Before first call, the reader needs to be positioned to the first record
3106 * by calling XLogPrefetcherBeginRead().
3107 *
3108 * If no valid record is available, returns NULL, or fails if emode is PANIC.
3109 * (emode must be either PANIC, LOG). In standby mode, retries until a valid
3110 * record is available.
3111 */
3112static XLogRecord *
3114 bool fetching_ckpt, TimeLineID replayTLI)
3115{
3116 XLogRecord *record;
3119
3121
3122 /* Pass through parameters to XLogPageRead */
3123 private->fetching_ckpt = fetching_ckpt;
3124 private->emode = emode;
3125 private->randAccess = !XLogRecPtrIsValid(xlogreader->ReadRecPtr);
3126 private->replayTLI = replayTLI;
3127
3128 /* This is the first attempt to read this page. */
3129 lastSourceFailed = false;
3130
3131 for (;;)
3132 {
3133 char *errormsg;
3134
3135 record = XLogPrefetcherReadRecord(xlogprefetcher, &errormsg);
3136 if (record == NULL)
3137 {
3138 /*
3139 * When we find that WAL ends in an incomplete record, keep track
3140 * of that record. After recovery is done, we'll write a record
3141 * to indicate to downstream WAL readers that that portion is to
3142 * be ignored.
3143 *
3144 * However, when ArchiveRecoveryRequested = true, we're going to
3145 * switch to a new timeline at the end of recovery. We will only
3146 * copy WAL over to the new timeline up to the end of the last
3147 * complete record, so if we did this, we would later create an
3148 * overwrite contrecord in the wrong place, breaking everything.
3149 */
3152 {
3155 }
3156
3157 if (readFile >= 0)
3158 {
3159 close(readFile);
3160 readFile = -1;
3161 }
3162
3163 /*
3164 * We only end up here without a message when XLogPageRead()
3165 * failed - in that case we already logged something. In
3166 * StandbyMode that only happens if we have been triggered, so we
3167 * shouldn't loop anymore in that case.
3168 */
3169 if (errormsg)
3171 (errmsg_internal("%s", errormsg) /* already translated */ ));
3172 }
3173
3174 /*
3175 * Check page TLI is one of the expected values.
3176 */
3178 {
3179 char fname[MAXFNAMELEN];
3180 XLogSegNo segno;
3181 int32 offset;
3182
3186 XLogFileName(fname, xlogreader->seg.ws_tli, segno,
3189 errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%08X, offset %u",
3191 fname,
3193 offset));
3194 record = NULL;
3195 }
3196
3197 if (record)
3198 {
3199 /* Great, got a record */
3200 return record;
3201 }
3202 else
3203 {
3204 /* No valid record available from this source */
3205 lastSourceFailed = true;
3206
3207 /*
3208 * If archive recovery was requested, but we were still doing
3209 * crash recovery, switch to archive recovery and retry using the
3210 * offline archive. We have now replayed all the valid WAL in
3211 * pg_wal, so we are presumably now consistent.
3212 *
3213 * We require that there's at least some valid WAL present in
3214 * pg_wal, however (!fetching_ckpt). We could recover using the
3215 * WAL from the archive, even if pg_wal is completely empty, but
3216 * we'd have no idea how far we'd have to replay to reach
3217 * consistency. So err on the safe side and give up.
3218 */
3220 !fetching_ckpt)
3221 {
3223 (errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
3224 InArchiveRecovery = true;
3227
3230 minRecoveryPointTLI = replayTLI;
3231
3233
3234 /*
3235 * Before we retry, reset lastSourceFailed and currentSource
3236 * so that we will check the archive next.
3237 */
3238 lastSourceFailed = false;
3240
3241 continue;
3242 }
3243
3244 /* In standby mode, loop back to retry. Otherwise, give up. */
3246 continue;
3247 else
3248 return NULL;
3249 }
3250 }
3251}
3252
3253/*
3254 * Read the XLOG page containing targetPagePtr into readBuf (if not read
3255 * already). Returns number of bytes read, if the page is read successfully,
3256 * or XLREAD_FAIL in case of errors. When errors occur, they are ereport'ed,
3257 * but only if they have not been previously reported.
3258 *
3259 * See XLogReaderRoutine.page_read for more details.
3260 *
3261 * While prefetching, xlogreader->nonblocking may be set. In that case,
3262 * returns XLREAD_WOULDBLOCK if we'd otherwise have to wait for more WAL.
3263 *
3264 * This is responsible for restoring files from archive as needed, as well
3265 * as for waiting for the requested WAL record to arrive in standby mode.
3266 *
3267 * xlogreader->private_data->emode specifies the log level used for reporting
3268 * "file not found" or "end of WAL" situations in archive recovery, or in
3269 * standby mode when promotion is triggered. If set to WARNING or below,
3270 * XLogPageRead() returns XLREAD_FAIL in those situations, on higher log
3271 * levels the ereport() won't return.
3272 *
3273 * In standby mode, if after a successful return of XLogPageRead() the
3274 * caller finds the record it's interested in to be broken, it should
3275 * ereport the error with the level determined by
3276 * emode_for_corrupt_record(), and then set lastSourceFailed
3277 * and call XLogPageRead() again with the same arguments. This lets
3278 * XLogPageRead() to try fetching the record from another source, or to
3279 * sleep and retry.
3280 */
3281static int
3283 XLogRecPtr targetRecPtr, char *readBuf)
3284{
3285 XLogPageReadPrivate *private =
3287 int emode = private->emode;
3290 ssize_t r;
3292
3294
3297
3298 /*
3299 * See if we need to switch to a new segment because the requested record
3300 * is not in the currently open one.
3301 */
3302 if (readFile >= 0 &&
3304 {
3305 /*
3306 * Request a restartpoint if we've replayed too much xlog since the
3307 * last one.
3308 */
3310 {
3312 {
3313 (void) GetRedoRecPtr();
3316 }
3317 }
3318
3319 close(readFile);
3320 readFile = -1;
3322 }
3323
3325
3326retry:
3327 /* See if we need to retrieve more data */
3328 if (readFile < 0 ||
3331 {
3332 if (readFile >= 0 &&
3336 return XLREAD_WOULDBLOCK;
3337
3339 private->randAccess,
3340 private->fetching_ckpt,
3342 private->replayTLI,
3345 {
3346 case XLREAD_WOULDBLOCK:
3347 return XLREAD_WOULDBLOCK;
3348 case XLREAD_FAIL:
3349 if (readFile >= 0)
3350 close(readFile);
3351 readFile = -1;
3352 readLen = 0;
3354 return XLREAD_FAIL;
3355 case XLREAD_SUCCESS:
3356 break;
3357 }
3358 }
3359
3360 /*
3361 * At this point, we have the right segment open and if we're streaming we
3362 * know the requested record is in it.
3363 */
3364 Assert(readFile != -1);
3365
3366 /*
3367 * If the current segment is being streamed from the primary, calculate
3368 * how much of the current page we have received already. We know the
3369 * requested record has been received, but this is for the benefit of
3370 * future calls, to allow quick exit at the top of this function.
3371 */
3373 {
3376 else
3379 }
3380 else
3382
3383 /* Read the requested page */
3385
3386 /* Measure I/O timing when reading segment */
3388
3390 r = pg_pread(readFile, readBuf, XLOG_BLCKSZ, (pgoff_t) readOff);
3391 if (r != XLOG_BLCKSZ)
3392 {
3393 char fname[MAXFNAMELEN];
3394 int save_errno = errno;
3395
3397
3398 /* Count I/O stats only for successful short reads */
3399 if (r > 0)
3401 io_start, 1, r);
3402
3404 if (r < 0)
3405 {
3406 errno = save_errno;
3409 errmsg("could not read from WAL segment %s, LSN %X/%08X, offset %u: %m",
3411 readOff)));
3412 }
3413 else
3416 errmsg("could not read from WAL segment %s, LSN %X/%08X, offset %u: read %zd of %zu",
3418 readOff, r, (Size) XLOG_BLCKSZ)));
3420 }
3422
3424 io_start, 1, r);
3425
3428 Assert(reqLen <= readLen);
3429
3431
3432 /*
3433 * Check the page header immediately, so that we can retry immediately if
3434 * it's not valid. This may seem unnecessary, because ReadPageInternal()
3435 * validates the page header anyway, and would propagate the failure up to
3436 * ReadRecord(), which would retry. However, there's a corner case with
3437 * continuation records, if a record is split across two pages such that
3438 * we would need to read the two pages from different sources across two
3439 * WAL segments.
3440 *
3441 * The first page is only available locally, in pg_wal, because it's
3442 * already been recycled on the primary. The second page, however, is not
3443 * present in pg_wal, and we should stream it from the primary. There is a
3444 * recycled WAL segment present in pg_wal, with garbage contents, however.
3445 * We would read the first page from the local WAL segment, but when
3446 * reading the second page, we would read the bogus, recycled, WAL
3447 * segment. If we didn't catch that case here, we would never recover,
3448 * because ReadRecord() would retry reading the whole record from the
3449 * beginning.
3450 *
3451 * Of course, this only catches errors in the page header, which is what
3452 * happens in the case of a recycled WAL segment. Other kinds of errors or
3453 * corruption still has the same problem. But this at least fixes the
3454 * common case, which can happen as part of normal operation.
3455 *
3456 * Validating the page header is cheap enough that doing it twice
3457 * shouldn't be a big deal from a performance point of view.
3458 *
3459 * When not in standby mode, an invalid page header should cause recovery
3460 * to end, not retry reading the page, so we don't need to validate the
3461 * page header here for the retry. Instead, ReadPageInternal() is
3462 * responsible for the validation.
3463 */
3464 if (StandbyMode &&
3467 {
3468 /*
3469 * Emit this error right now then retry this page immediately. Use
3470 * errmsg_internal() because the message was already translated.
3471 */
3472 if (xlogreader->errormsg_buf[0])
3475
3476 /* reset any error XLogReaderValidatePageHeader() might have set */
3479 }
3480
3481 return readLen;
3482
3484
3485 /*
3486 * If we're reading ahead, give up fast. Retries and error reporting will
3487 * be handled by a later read when recovery catches up to this point.
3488 */
3490 return XLREAD_WOULDBLOCK;
3491
3492 lastSourceFailed = true;
3493
3494 if (readFile >= 0)
3495 close(readFile);
3496 readFile = -1;
3497 readLen = 0;
3499
3500 /* In standby-mode, keep trying */
3501 if (StandbyMode)
3502 goto retry;
3503 else
3504 return XLREAD_FAIL;
3505}
3506
3507/*
3508 * Open the WAL segment containing WAL location 'RecPtr'.
3509 *
3510 * The segment can be fetched via restore_command, or via walreceiver having
3511 * streamed the record, or it can already be present in pg_wal. Checking
3512 * pg_wal is mainly for crash recovery, but it will be polled in standby mode
3513 * too, in case someone copies a new segment directly to pg_wal. That is not
3514 * documented or recommended, though.
3515 *
3516 * If 'fetching_ckpt' is true, we're fetching a checkpoint record, and should
3517 * prepare to read WAL starting from RedoStartLSN after this.
3518 *
3519 * 'RecPtr' might not point to the beginning of the record we're interested
3520 * in, it might also point to the page or segment header. In that case,
3521 * 'tliRecPtr' is the position of the WAL record we're interested in. It is
3522 * used to decide which timeline to stream the requested WAL from.
3523 *
3524 * 'replayLSN' is the current replay LSN, so that if we scan for new
3525 * timelines, we can reject a switch to a timeline that branched off before
3526 * this point.
3527 *
3528 * If the record is not immediately available, the function returns XLREAD_FAIL
3529 * if we're not in standby mode. In standby mode, the function waits for it to
3530 * become available.
3531 *
3532 * When the requested record becomes available, the function opens the file
3533 * containing it (if not open already), and returns XLREAD_SUCCESS. When end
3534 * of standby mode is triggered by the user, and there is no more WAL
3535 * available, returns XLREAD_FAIL.
3536 *
3537 * If nonblocking is true, then give up immediately if we can't satisfy the
3538 * request, returning XLREAD_WOULDBLOCK instead of waiting.
3539 */
3540static XLogPageReadResult
3542 bool fetching_ckpt, XLogRecPtr tliRecPtr,
3543 TimeLineID replayTLI, XLogRecPtr replayLSN,
3544 bool nonblocking)
3545{
3546 static TimestampTz last_fail_time = 0;
3548 bool streaming_reply_sent = false;
3549
3550 /*-------
3551 * Standby mode is implemented by a state machine:
3552 *
3553 * 1. Read from either archive or pg_wal (XLOG_FROM_ARCHIVE), or just
3554 * pg_wal (XLOG_FROM_PG_WAL)
3555 * 2. Check for promotion trigger request
3556 * 3. Read from primary server via walreceiver (XLOG_FROM_STREAM)
3557 * 4. Rescan timelines
3558 * 5. Sleep wal_retrieve_retry_interval milliseconds, and loop back to 1.
3559 *
3560 * Failure to read from the current source advances the state machine to
3561 * the next state.
3562 *
3563 * 'currentSource' indicates the current state. There are no currentSource
3564 * values for "check trigger", "rescan timelines", and "sleep" states,
3565 * those actions are taken when reading from the previous source fails, as
3566 * part of advancing to the next state.
3567 *
3568 * If standby mode is turned off while reading WAL from stream, we move
3569 * to XLOG_FROM_ARCHIVE and reset lastSourceFailed, to force fetching
3570 * the files (which would be required at end of recovery, e.g., timeline
3571 * history file) from archive or pg_wal. We don't need to kill WAL receiver
3572 * here because it's already stopped when standby mode is turned off at
3573 * the end of recovery.
3574 *-------
3575 */
3576 if (!InArchiveRecovery)
3578 else if (currentSource == XLOG_FROM_ANY ||
3580 {
3581 lastSourceFailed = false;
3583 }
3584
3585 for (;;)
3586 {
3588 bool startWalReceiver = false;
3589
3590 /*
3591 * First check if we failed to read from the current source, and
3592 * advance the state machine if so. The failure to read might've
3593 * happened outside this function, e.g when a CRC check fails on a
3594 * record, or within this loop.
3595 */
3596 if (lastSourceFailed)
3597 {
3598 /*
3599 * Don't allow any retry loops to occur during nonblocking
3600 * readahead. Let the caller process everything that has been
3601 * decoded already first.
3602 */
3603 if (nonblocking)
3604 return XLREAD_WOULDBLOCK;
3605
3606 switch (currentSource)
3607 {
3608 case XLOG_FROM_ARCHIVE:
3609 case XLOG_FROM_PG_WAL:
3610
3611 /*
3612 * Check to see if promotion is requested. Note that we do
3613 * this only after failure, so when you promote, we still
3614 * finish replaying as much as we can from archive and
3615 * pg_wal before failover.
3616 */
3618 {
3620 return XLREAD_FAIL;
3621 }
3622
3623 /*
3624 * Not in standby mode, and we've now tried the archive
3625 * and pg_wal.
3626 */
3627 if (!StandbyMode)
3628 return XLREAD_FAIL;
3629
3630 /*
3631 * Move to XLOG_FROM_STREAM state, and set to start a
3632 * walreceiver if necessary.
3633 */
3635 startWalReceiver = true;
3636 break;
3637
3638 case XLOG_FROM_STREAM:
3639
3640 /*
3641 * Failure while streaming. Most likely, we got here
3642 * because streaming replication was terminated, or
3643 * promotion was triggered. But we also get here if we
3644 * find an invalid record in the WAL streamed from the
3645 * primary, in which case something is seriously wrong.
3646 * There's little chance that the problem will just go
3647 * away, but PANIC is not good for availability either,
3648 * especially in hot standby mode. So, we treat that the
3649 * same as disconnection, and retry from archive/pg_wal
3650 * again. The WAL in the archive should be identical to
3651 * what was streamed, so it's unlikely that it helps, but
3652 * one can hope...
3653 */
3654
3655 /*
3656 * We should be able to move to XLOG_FROM_STREAM only in
3657 * standby mode.
3658 */
3660
3661 /*
3662 * Before we leave XLOG_FROM_STREAM state, make sure that
3663 * walreceiver is not active, so that it won't overwrite
3664 * WAL that we restore from archive.
3665 *
3666 * If walreceiver is actively streaming (or attempting to
3667 * connect), we must shut it down. However, if it's
3668 * already in WAITING state (e.g., due to timeline
3669 * divergence), we only need to reset the install flag to
3670 * allow archive restoration.
3671 */
3672 if (WalRcvStreaming())
3674 else
3675 {
3676 /*
3677 * WALRCV_STOPPING state is a transient state while
3678 * the startup process is in ShutdownWalRcv(). It
3679 * should never appear here since we would be waiting
3680 * for the walreceiver to reach WALRCV_STOPPED in that
3681 * case.
3682 */
3685 }
3686
3687 /*
3688 * Before we sleep, re-scan for possible new timelines if
3689 * we were requested to recover to the latest timeline.
3690 */
3692 {
3693 if (rescanLatestTimeLine(replayTLI, replayLSN))
3694 {
3696 break;
3697 }
3698 }
3699
3700 /*
3701 * XLOG_FROM_STREAM is the last state in our state
3702 * machine, so we've exhausted all the options for
3703 * obtaining the requested WAL. We're going to loop back
3704 * and retry from the archive, but if it hasn't been long
3705 * since last attempt, sleep wal_retrieve_retry_interval
3706 * milliseconds to avoid busy-waiting.
3707 */
3711 {
3712 long wait_time;
3713
3714 wait_time = wal_retrieve_retry_interval -
3716
3717 elog(LOG, "waiting for WAL to become available at %X/%08X",
3719
3720 /* Do background tasks that might benefit us later. */
3722
3726 wait_time,
3730
3731 /* Handle interrupt signals of startup process */
3733 }
3736 break;
3737
3738 default:
3739 elog(ERROR, "unexpected WAL source %d", currentSource);
3740 }
3741 }
3742 else if (currentSource == XLOG_FROM_PG_WAL)
3743 {
3744 /*
3745 * We just successfully read a file in pg_wal. We prefer files in
3746 * the archive over ones in pg_wal, so try the next file again
3747 * from the archive first.
3748 */
3751 }
3752
3753 if (currentSource != oldSource)
3754 elog(DEBUG2, "switched WAL source from %s to %s after %s",
3756 lastSourceFailed ? "failure" : "success");
3757
3758 /*
3759 * We've now handled possible failure. Try to read from the chosen
3760 * source.
3761 */
3762 lastSourceFailed = false;
3763
3764 switch (currentSource)
3765 {
3766 case XLOG_FROM_ARCHIVE:
3767 case XLOG_FROM_PG_WAL:
3768
3769 /*
3770 * WAL receiver must not be running when reading WAL from
3771 * archive or pg_wal.
3772 */
3774
3775 /* Close any old file we might have open. */
3776 if (readFile >= 0)
3777 {
3778 close(readFile);
3779 readFile = -1;
3780 }
3781 /* Reset curFileTLI if random fetch. */
3782 if (randAccess)
3783 curFileTLI = 0;
3784
3785 /*
3786 * Try to restore the file from archive, or read an existing
3787 * file from pg_wal.
3788 */
3792 if (readFile >= 0)
3793 return XLREAD_SUCCESS; /* success! */
3794
3795 /*
3796 * Nope, not found in archive or pg_wal.
3797 */
3798 lastSourceFailed = true;
3799 break;
3800
3801 case XLOG_FROM_STREAM:
3802 {
3803 bool havedata;
3804
3805 /*
3806 * We should be able to move to XLOG_FROM_STREAM only in
3807 * standby mode.
3808 */
3810
3811 /*
3812 * First, shutdown walreceiver if its restart has been
3813 * requested -- but no point if we're already slated for
3814 * starting it.
3815 */
3817 {
3819
3820 /*
3821 * Re-scan for possible new timelines if we were
3822 * requested to recover to the latest timeline.
3823 */
3826 rescanLatestTimeLine(replayTLI, replayLSN);
3827
3828 startWalReceiver = true;
3829 }
3830 pendingWalRcvRestart = false;
3831
3832 /*
3833 * Launch walreceiver if needed.
3834 *
3835 * If fetching_ckpt is true, RecPtr points to the initial
3836 * checkpoint location. In that case, we use RedoStartLSN
3837 * as the streaming start position instead of RecPtr, so
3838 * that when we later jump backwards to start redo at
3839 * RedoStartLSN, we will have the logs streamed already.
3840 */
3841 if (startWalReceiver &&
3843 {
3844 XLogRecPtr ptr;
3845 TimeLineID tli;
3846
3847 if (fetching_ckpt)
3848 {
3849 ptr = RedoStartLSN;
3850 tli = RedoStartTLI;
3851 }
3852 else
3853 {
3854 ptr = RecPtr;
3855
3856 /*
3857 * Use the record begin position to determine the
3858 * TLI, rather than the position we're reading.
3859 */
3861
3862 if (curFileTLI > 0 && tli < curFileTLI)
3863 elog(ERROR, "according to history file, WAL location %X/%08X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3865 tli, curFileTLI);
3866 }
3867 curFileTLI = tli;
3873 }
3874
3875 /*
3876 * Check if WAL receiver is active or wait to start up.
3877 */
3878 if (!WalRcvStreaming())
3879 {
3880 lastSourceFailed = true;
3881 break;
3882 }
3883
3884 /*
3885 * Walreceiver is active, so see if new data has arrived.
3886 *
3887 * We only advance XLogReceiptTime when we obtain fresh
3888 * WAL from walreceiver and observe that we had already
3889 * processed everything before the most recent "chunk"
3890 * that it flushed to disk. In steady state where we are
3891 * keeping up with the incoming data, XLogReceiptTime will
3892 * be updated on each cycle. When we are behind,
3893 * XLogReceiptTime will not advance, so the grace time
3894 * allotted to conflicting queries will decrease.
3895 */
3896 if (RecPtr < flushedUpto)
3897 havedata = true;
3898 else
3899 {
3900 XLogRecPtr latestChunkStart;
3901
3902 flushedUpto = GetWalRcvFlushRecPtr(&latestChunkStart, &receiveTLI);
3904 {
3905 havedata = true;
3906 if (latestChunkStart <= RecPtr)
3907 {
3910 }
3911 }
3912 else
3913 havedata = false;
3914 }
3915 if (havedata)
3916 {
3917 /*
3918 * Great, streamed far enough. Open the file if it's
3919 * not open already. Also read the timeline history
3920 * file if we haven't initialized timeline history
3921 * yet; it should be streamed over and present in
3922 * pg_wal by now. Use XLOG_FROM_STREAM so that source
3923 * info is set correctly and XLogReceiptTime isn't
3924 * changed.
3925 *
3926 * NB: We must set readTimeLineHistory based on
3927 * recoveryTargetTLI, not receiveTLI. Normally they'll
3928 * be the same, but if recovery_target_timeline is
3929 * 'latest' and archiving is configured, then it's
3930 * possible that we managed to retrieve one or more
3931 * new timeline history files from the archive,
3932 * updating recoveryTargetTLI.
3933 */
3934 if (readFile < 0)
3935 {
3936 if (!expectedTLEs)
3939 XLOG_FROM_STREAM, false);
3940 Assert(readFile >= 0);
3941 }
3942 else
3943 {
3944 /* just make sure source info is correct... */
3947 return XLREAD_SUCCESS;
3948 }
3949 break;
3950 }
3951
3952 /* In nonblocking mode, return rather than sleeping. */
3953 if (nonblocking)
3954 return XLREAD_WOULDBLOCK;
3955
3956 /*
3957 * Data not here yet. Check for trigger, then wait for
3958 * walreceiver to wake us up when new WAL arrives.
3959 */
3961 {
3962 /*
3963 * Note that we don't return XLREAD_FAIL immediately
3964 * here. After being triggered, we still want to
3965 * replay all the WAL that was already streamed. It's
3966 * in pg_wal now, so we just treat this as a failure,
3967 * and the state machine will move on to replay the
3968 * streamed WAL from pg_wal, and then recheck the
3969 * trigger and exit replay.
3970 */
3971 lastSourceFailed = true;
3972 break;
3973 }
3974
3975 /*
3976 * Since we have replayed everything we have received so
3977 * far and are about to start waiting for more WAL, let's
3978 * tell the upstream server our replay location now so
3979 * that pg_stat_replication doesn't show stale
3980 * information.
3981 */
3983 {
3985 streaming_reply_sent = true;
3986 }
3987
3988 /* Do any background tasks that might benefit us later. */
3990
3991 /* Update pg_stat_recovery_prefetch before sleeping. */
3993
3994 /*
3995 * Wait for more WAL to arrive, when we will be woken
3996 * immediately by the WAL receiver.
3997 */
4000 -1L,
4003 break;
4004 }
4005
4006 default:
4007 elog(ERROR, "unexpected WAL source %d", currentSource);
4008 }
4009
4010 /*
4011 * Check for recovery pause here so that we can confirm more quickly
4012 * that a requested pause has actually taken effect.
4013 */
4014 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
4016 recoveryPausesHere(false);
4017
4018 /*
4019 * This possibly-long loop needs to handle interrupts of startup
4020 * process.
4021 */
4023 }
4024
4025 return XLREAD_FAIL; /* not reached */
4026}
4027
4028
4029/*
4030 * Determine what log level should be used to report a corrupt WAL record
4031 * in the current WAL page, previously read by XLogPageRead().
4032 *
4033 * 'emode' is the error mode that would be used to report a file-not-found
4034 * or legitimate end-of-WAL situation. Generally, we use it as-is, but if
4035 * we're retrying the exact same record that we've tried previously, only
4036 * complain the first time to keep the noise down. However, we only do when
4037 * reading from pg_wal, because we don't expect any invalid records in archive
4038 * or in records streamed from the primary. Files in the archive should be complete,
4039 * and we should never hit the end of WAL because we stop and wait for more WAL
4040 * to arrive before replaying it.
4041 *
4042 * NOTE: This function remembers the RecPtr value it was last called with,
4043 * to suppress repeated messages about the same record. Only call this when
4044 * you are about to ereport(), or you might cause a later message to be
4045 * erroneously suppressed.
4046 */
4047static int
4049{
4051
4052 if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
4053 {
4054 if (RecPtr == lastComplaint)
4055 emode = DEBUG1;
4056 else
4058 }
4059 return emode;
4060}
4061
4062
4063/*
4064 * Subroutine to try to fetch and validate a prior checkpoint record.
4065 */
4066static XLogRecord *
4068 TimeLineID replayTLI)
4069{
4070 XLogRecord *record;
4071 uint8 info;
4072
4074
4075 if (!XRecOffIsValid(RecPtr))
4076 {
4077 ereport(LOG,
4078 (errmsg("invalid checkpoint location")));
4079 return NULL;
4080 }
4081
4083 record = ReadRecord(xlogprefetcher, LOG, true, replayTLI);
4084
4085 if (record == NULL)
4086 {
4087 ereport(LOG,
4088 (errmsg("invalid checkpoint record")));
4089 return NULL;
4090 }
4091 if (record->xl_rmid != RM_XLOG_ID)
4092 {
4093 ereport(LOG,
4094 (errmsg("invalid resource manager ID in checkpoint record")));
4095 return NULL;
4096 }
4097 info = record->xl_info & ~XLR_INFO_MASK;
4098 if (info != XLOG_CHECKPOINT_SHUTDOWN &&
4099 info != XLOG_CHECKPOINT_ONLINE)
4100 {
4101 ereport(LOG,
4102 (errmsg("invalid xl_info in checkpoint record")));
4103 return NULL;
4104 }
4106 {
4107 ereport(LOG,
4108 (errmsg("invalid length of checkpoint record")));
4109 return NULL;
4110 }
4111 return record;
4112}
4113
4114/*
4115 * Scan for new timelines that might have appeared in the archive since we
4116 * started recovery.
4117 *
4118 * If there are any, the function changes recovery target TLI to the latest
4119 * one and returns 'true'.
4120 */
4121static bool
4123{
4125 bool found;
4126 ListCell *cell;
4130
4133 {
4134 /* No new timelines found */
4135 return false;
4136 }
4137
4138 /*
4139 * Determine the list of expected TLIs for the new TLI
4140 */
4141
4143
4144 /*
4145 * If the current timeline is not part of the history of the new timeline,
4146 * we cannot proceed to it.
4147 */
4148 found = false;
4149 foreach(cell, newExpectedTLEs)
4150 {
4152
4153 if (currentTle->tli == recoveryTargetTLI)
4154 {
4155 found = true;
4156 break;
4157 }
4158 }
4159 if (!found)
4160 {
4161 ereport(LOG,
4162 (errmsg("new timeline %u is not a child of database system timeline %u",
4163 newtarget,
4164 replayTLI)));
4165 return false;
4166 }
4167
4168 /*
4169 * The current timeline was found in the history file, but check that the
4170 * next timeline was forked off from it *after* the current recovery
4171 * location.
4172 */
4173 if (currentTle->end < replayLSN)
4174 {
4175 ereport(LOG,
4176 errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%08X",
4177 newtarget,
4178 replayTLI,
4180 return false;
4181 }
4182
4183 /* The new timeline history seems valid. Switch target */
4187
4188 /*
4189 * As in StartupXLOG(), try to ensure we have all the history files
4190 * between the old target and new target in pg_wal.
4191 */
4193
4194 ereport(LOG,
4195 (errmsg("new target timeline is %u",
4197
4198 return true;
4199}
4200
4201
4202/*
4203 * Open a logfile segment for reading (during recovery).
4204 *
4205 * If source == XLOG_FROM_ARCHIVE, the segment is retrieved from archive.
4206 * Otherwise, it's assumed to be already available in pg_wal.
4207 */
4208static int
4211{
4212 char xlogfname[MAXFNAMELEN];
4213 char activitymsg[MAXFNAMELEN + 16];
4214 char path[MAXPGPATH];
4215 int fd;
4216
4218
4219 switch (source)
4220 {
4221 case XLOG_FROM_ARCHIVE:
4222 /* Report recovery progress in PS display */
4223 snprintf(activitymsg, sizeof(activitymsg), "waiting for %s",
4224 xlogfname);
4226
4227 if (!RestoreArchivedFile(path, xlogfname,
4228 "RECOVERYXLOG",
4230 InRedo))
4231 return -1;
4232 break;
4233
4234 case XLOG_FROM_PG_WAL:
4235 case XLOG_FROM_STREAM:
4236 XLogFilePath(path, tli, segno, wal_segment_size);
4237 break;
4238
4239 default:
4240 elog(ERROR, "invalid XLogFileRead source %d", source);
4241 }
4242
4243 /*
4244 * If the segment was fetched from archival storage, replace the existing
4245 * xlog segment (if any) with the archival version.
4246 */
4248 {
4251
4252 /*
4253 * Set path to point at the new file in pg_wal.
4254 */
4255 snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
4256 }
4257
4259 if (fd >= 0)
4260 {
4261 /* Success! */
4262 curFileTLI = tli;
4263
4264 /* Report recovery progress in PS display */
4265 snprintf(activitymsg, sizeof(activitymsg), "recovering %s",
4266 xlogfname);
4268
4269 /* Track source of data in assorted state variables */
4272 /* In FROM_STREAM case, caller tracks receipt time, not me */
4273 if (source != XLOG_FROM_STREAM)
4275
4276 return fd;
4277 }
4278 if (errno != ENOENT || !notfoundOk) /* unexpected failure? */
4279 ereport(PANIC,
4281 errmsg("could not open file \"%s\": %m", path)));
4282 return -1;
4283}
4284
4285/*
4286 * Open a logfile segment for reading (during recovery).
4287 *
4288 * This version searches for the segment with any TLI listed in expectedTLEs.
4289 */
4290static int
4292{
4293 char path[MAXPGPATH];
4294 ListCell *cell;
4295 int fd;
4296 List *tles;
4297
4298 /*
4299 * Loop looking for a suitable timeline ID: we might need to read any of
4300 * the timelines listed in expectedTLEs.
4301 *
4302 * We expect curFileTLI on entry to be the TLI of the preceding file in
4303 * sequence, or 0 if there was no predecessor. We do not allow curFileTLI
4304 * to go backwards; this prevents us from picking up the wrong file when a
4305 * parent timeline extends to higher segment numbers than the child we
4306 * want to read.
4307 *
4308 * If we haven't read the timeline history file yet, read it now, so that
4309 * we know which TLIs to scan. We don't save the list in expectedTLEs,
4310 * however, unless we actually find a valid segment. That way if there is
4311 * neither a timeline history file nor a WAL segment in the archive, and
4312 * streaming replication is set up, we'll read the timeline history file
4313 * streamed from the primary when we start streaming, instead of
4314 * recovering with a dummy history generated here.
4315 */
4316 if (expectedTLEs)
4318 else
4320
4321 foreach(cell, tles)
4322 {
4324 TimeLineID tli = hent->tli;
4325
4326 if (tli < curFileTLI)
4327 break; /* don't bother looking at too-old TLIs */
4328
4329 /*
4330 * Skip scanning the timeline ID that the logfile segment to read
4331 * doesn't belong to
4332 */
4333 if (XLogRecPtrIsValid(hent->begin))
4334 {
4335 XLogSegNo beginseg = 0;
4336
4338
4339 /*
4340 * The logfile segment that doesn't belong to the timeline is
4341 * older or newer than the segment that the timeline started or
4342 * ended at, respectively. It's sufficient to check only the
4343 * starting segment of the timeline here. Since the timelines are
4344 * scanned in descending order in this loop, any segments newer
4345 * than the ending segment should belong to newer timeline and
4346 * have already been read before. So it's not necessary to check
4347 * the ending segment of the timeline here.
4348 */
4349 if (segno < beginseg)
4350 continue;
4351 }
4352
4354 {
4355 fd = XLogFileRead(segno, tli, XLOG_FROM_ARCHIVE, true);
4356 if (fd != -1)
4357 {
4358 elog(DEBUG1, "got WAL segment from archive");
4359 if (!expectedTLEs)
4361 return fd;
4362 }
4363 }
4364
4366 {
4367 fd = XLogFileRead(segno, tli, XLOG_FROM_PG_WAL, true);
4368 if (fd != -1)
4369 {
4370 if (!expectedTLEs)
4372 return fd;
4373 }
4374 }
4375 }
4376
4377 /* Couldn't find it. For simplicity, complain about front timeline */
4379 errno = ENOENT;
4382 errmsg("could not open file \"%s\": %m", path)));
4383 return -1;
4384}
4385
4386/*
4387 * Set flag to signal the walreceiver to restart. (The startup process calls
4388 * this on noticing a relevant configuration change.)
4389 */
4390void
4392{
4394 {
4395 ereport(LOG,
4396 (errmsg("WAL receiver process shutdown requested")));
4397
4398 pendingWalRcvRestart = true;
4399 }
4400}
4401
4402
4403/*
4404 * Has a standby promotion already been triggered?
4405 *
4406 * Unlike CheckForStandbyTrigger(), this works in any process
4407 * that's connected to shared memory.
4408 */
4409bool
4411{
4412 /*
4413 * We check shared state each time only until a standby promotion is
4414 * triggered. We can't trigger a promotion again, so there's no need to
4415 * keep checking after the shared variable has once been seen true.
4416 */
4418 return true;
4419
4423
4425}
4426
4427static void
4429{
4433
4434 /*
4435 * Mark the recovery pause state as 'not paused' because the paused state
4436 * ends and promotion continues if a promotion is triggered while recovery
4437 * is paused. Otherwise pg_get_wal_replay_pause_state() can mistakenly
4438 * return 'paused' while a promotion is ongoing.
4439 */
4440 SetRecoveryPause(false);
4441
4443}
4444
4445/*
4446 * Check whether a promote request has arrived.
4447 */
4448static bool
4450{
4452 return true;
4453
4455 {
4456 ereport(LOG, (errmsg("received promote request")));
4460 return true;
4461 }
4462
4463 return false;
4464}
4465
4466/*
4467 * Remove the files signaling a standby promotion request.
4468 */
4469void
4474
4475/*
4476 * Check to see if a promote request has arrived.
4477 */
4478bool
4480{
4481 struct stat stat_buf;
4482
4483 if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4484 return true;
4485
4486 return false;
4487}
4488
4489/*
4490 * Wake up startup process to replay newly arrived WAL, or to notice that
4491 * failover has been requested.
4492 */
4493void
4498
4499/*
4500 * Schedule a walreceiver wakeup in the main recovery loop.
4501 */
4502void
4507
4508/*
4509 * Is HotStandby active yet? This is only important in special backends
4510 * since normal backends won't ever be able to connect until this returns
4511 * true. Postmaster knows this by way of signal, not via shared memory.
4512 *
4513 * Unlike testing standbyState, this works in any process that's connected to
4514 * shared memory. (And note that standbyState alone doesn't tell the truth
4515 * anyway.)
4516 */
4517bool
4519{
4520 /*
4521 * We check shared state each time only until Hot Standby is active. We
4522 * can't de-activate Hot Standby, so there's no need to keep checking
4523 * after the shared variable has once been seen true.
4524 */
4526 return true;
4527 else
4528 {
4529 /* spinlock is essential on machines with weak memory ordering! */
4533
4534 return LocalHotStandbyActive;
4535 }
4536}
4537
4538/*
4539 * Like HotStandbyActive(), but to be used only in WAL replay code,
4540 * where we don't need to ask any other process what the state is.
4541 */
4542static bool
4548
4549/*
4550 * Get latest redo apply position.
4551 *
4552 * Exported to allow WALReceiver to read the pointer directly.
4553 */
4556{
4558 TimeLineID tli;
4559
4564
4565 if (replayTLI)
4566 *replayTLI = tli;
4567 return recptr;
4568}
4569
4570
4571/*
4572 * Get position of last applied, or the record being applied.
4573 *
4574 * This is different from GetXLogReplayRecPtr() in that if a WAL
4575 * record is currently being applied, this includes that record.
4576 */
4579{
4581 TimeLineID tli;
4582
4587
4588 if (replayEndTLI)
4589 *replayEndTLI = tli;
4590 return recptr;
4591}
4592
4593/*
4594 * Save timestamp of latest processed commit/abort record.
4595 *
4596 * We keep this in XLogRecoveryCtl, not a simple static variable, so that it can be
4597 * seen by processes other than the startup process. Note in particular
4598 * that CreateRestartPoint is executed in the checkpointer.
4599 */
4600static void
4607
4608/*
4609 * Fetch timestamp of latest processed commit/abort record.
4610 */
4622
4623/*
4624 * Save timestamp of the next chunk of WAL records to apply.
4625 *
4626 * We keep this in XLogRecoveryCtl, not a simple static variable, so that it can be
4627 * seen by all backends.
4628 */
4629static void
4636
4637/*
4638 * Fetch timestamp of latest processed commit/abort record.
4639 * Startup process maintains an accurate local copy in XLogReceiptTime
4640 */
4652
4653/*
4654 * Returns time of receipt of current chunk of XLOG data, as well as
4655 * whether it was received from streaming replication or from archives.
4656 */
4657void
4659{
4660 /*
4661 * This must be executed in the startup process, since we don't export the
4662 * relevant state to shared memory.
4663 */
4665
4668}
4669
4670/*
4671 * Note that text field supplied is a parameter name and does not require
4672 * translation
4673 */
4674void
4676{
4677 if (currValue < minValue)
4678 {
4680 {
4681 bool warned_for_promote = false;
4682
4685 errmsg("hot standby is not possible because of insufficient parameter settings"),
4686 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4687 param_name,
4688 currValue,
4689 minValue)));
4690
4691 SetRecoveryPause(true);
4692
4693 ereport(LOG,
4694 (errmsg("recovery has paused"),
4695 errdetail("If recovery is unpaused, the server will shut down."),
4696 errhint("You can then restart the server after making the necessary configuration changes.")));
4697
4699 {
4701
4703 {
4704 if (!warned_for_promote)
4707 errmsg("promotion is not possible because of insufficient parameter settings"),
4708
4709 /*
4710 * Repeat the detail from above so it's easy to find
4711 * in the log.
4712 */
4713 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4714 param_name,
4715 currValue,
4716 minValue),
4717 errhint("Restart the server after making the necessary configuration changes.")));
4718 warned_for_promote = true;
4719 }
4720
4721 /*
4722 * If recovery pause is requested then set it paused. While
4723 * we are in the loop, user might resume and pause again so
4724 * set this every time.
4725 */
4727
4728 /*
4729 * We wait on a condition variable that will wake us as soon
4730 * as the pause ends, but we use a timeout so we can check the
4731 * above conditions periodically too.
4732 */
4735 }
4737 }
4738
4739 ereport(FATAL,
4741 errmsg("recovery aborted because of insufficient parameter settings"),
4742 /* Repeat the detail from above so it's easy to find in the log. */
4743 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4744 param_name,
4745 currValue,
4746 minValue),
4747 errhint("You can restart the server after making the necessary configuration changes.")));
4748 }
4749}
4750
4751
4752/*
4753 * GUC check_hook for primary_slot_name
4754 */
4755bool
4757{
4758 int err_code;
4759 char *err_msg = NULL;
4760 char *err_hint = NULL;
4761
4762 if (*newval && strcmp(*newval, "") != 0 &&
4764 &err_msg, &err_hint))
4765 {
4767 GUC_check_errdetail("%s", err_msg);
4768 if (err_hint != NULL)
4770 return false;
4771 }
4772
4773 return true;
4774}
4775
4776/*
4777 * Return the recovery target derived from the recovery_target* settings,
4778 * raising an error if more than one of them is set.
4779 */
4780static RecoveryTargetType
4782{
4783 int ntargets = 0;
4785 const char *val;
4787
4789
4790#define ADD_TARGET_IF_SET(gucname, kind) \
4791 do { \
4792 val = GetConfigOption(gucname, false, false); \
4793 if (val[0] != '\0') \
4794 { \
4795 ntargets++; \
4796 target = (kind); \
4797 if (buf.len == 0) \
4798 appendStringInfo(&buf, _("\"%s\""), gucname); \
4799 else \
4800 appendStringInfo(&buf, _(", \"%s\""), gucname); \
4801 } \
4802 } while (0)
4803
4804 ADD_TARGET_IF_SET("recovery_target", RECOVERY_TARGET_IMMEDIATE);
4805 ADD_TARGET_IF_SET("recovery_target_lsn", RECOVERY_TARGET_LSN);
4806 ADD_TARGET_IF_SET("recovery_target_name", RECOVERY_TARGET_NAME);
4807 ADD_TARGET_IF_SET("recovery_target_time", RECOVERY_TARGET_TIME);
4808 ADD_TARGET_IF_SET("recovery_target_xid", RECOVERY_TARGET_XID);
4809#undef ADD_TARGET_IF_SET
4810
4811 if (ntargets > 1)
4812 ereport(FATAL,
4814 errmsg("cannot specify more than one recovery target"),
4815 errdetail("Parameters set are: %s.",
4816 buf.data));
4817
4818 pfree(buf.data);
4819
4820 return target;
4821}
4822
4823/*
4824 * GUC check_hook for recovery_target
4825 */
4826bool
4828{
4829 if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
4830 {
4831 GUC_check_errdetail("The only allowed value is \"immediate\".");
4832 return false;
4833 }
4834 return true;
4835}
4836
4837/*
4838 * GUC check_hook for recovery_target_lsn
4839 */
4840bool
4842{
4843 if (strcmp(*newval, "") != 0)
4844 {
4845 XLogRecPtr lsn;
4848
4849 lsn = pg_lsn_in_safe(*newval, (Node *) &escontext);
4850 if (escontext.error_occurred)
4851 return false;
4852
4853 myextra = (XLogRecPtr *) guc_malloc(LOG, sizeof(XLogRecPtr));
4854 if (!myextra)
4855 return false;
4856 *myextra = lsn;
4857 *extra = myextra;
4858 }
4859 return true;
4860}
4861
4862/*
4863 * GUC assign_hook for recovery_target_lsn
4864 */
4865void
4866assign_recovery_target_lsn(const char *newval, void *extra)
4867{
4868 if (newval && strcmp(newval, "") != 0)
4869 recoveryTargetLSN = *((XLogRecPtr *) extra);
4870}
4871
4872/*
4873 * GUC check_hook for recovery_target_name
4874 */
4875bool
4877{
4878 /* Use the value of newval directly */
4879 if (strlen(*newval) >= MAXFNAMELEN)
4880 {
4881 GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
4882 "recovery_target_name", MAXFNAMELEN - 1);
4883 return false;
4884 }
4885 return true;
4886}
4887
4888/*
4889 * GUC check_hook for recovery_target_time
4890 *
4891 * The interpretation of the recovery_target_time string can depend on the
4892 * time zone setting, so we need to wait until after all GUC processing is
4893 * done before we can do the final parsing of the string. This check function
4894 * only does a parsing pass to catch syntax errors, but we store the string
4895 * and parse it again when we need to use it.
4896 */
4897bool
4899{
4900 if (strcmp(*newval, "") != 0)
4901 {
4902 /* reject some special values */
4903 if (strcmp(*newval, "now") == 0 ||
4904 strcmp(*newval, "today") == 0 ||
4905 strcmp(*newval, "tomorrow") == 0 ||
4906 strcmp(*newval, "yesterday") == 0)
4907 {
4908 return false;
4909 }
4910
4911 /*
4912 * parse timestamp value (see also timestamptz_in())
4913 */
4914 {
4915 char *str = *newval;
4916 fsec_t fsec;
4917 struct pg_tm tt,
4918 *tm = &tt;
4919 int tz;
4920 int dtype;
4921 int nf;
4922 int dterr;
4923 char *field[MAXDATEFIELDS];
4924 int ftype[MAXDATEFIELDS];
4928
4930 field, ftype, MAXDATEFIELDS, &nf);
4931 if (dterr == 0)
4932 dterr = DecodeDateTime(field, ftype, nf,
4933 &dtype, tm, &fsec, &tz, &dtextra);
4934 if (dterr != 0)
4935 return false;
4936 if (dtype != DTK_DATE)
4937 return false;
4938
4939 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
4940 {
4941 GUC_check_errdetail("Timestamp out of range: \"%s\".", str);
4942 return false;
4943 }
4944 }
4945 }
4946 return true;
4947}
4948
4949/*
4950 * GUC check_hook for recovery_target_timeline
4951 */
4952bool
4954{
4957
4958 if (strcmp(*newval, "current") == 0)
4960 else if (strcmp(*newval, "latest") == 0)
4962 else
4963 {
4964 char *endp;
4965 uint64 timeline;
4966
4968
4969 errno = 0;
4970 timeline = strtou64(*newval, &endp, 0);
4971
4972 if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
4973 {
4974 GUC_check_errdetail("\"%s\" is not a valid number.",
4975 "recovery_target_timeline");
4976 return false;
4977 }
4978
4980 {
4981 GUC_check_errdetail("\"%s\" must be between %u and %u.",
4982 "recovery_target_timeline", 1, PG_UINT32_MAX);
4983 return false;
4984 }
4985 }
4986
4988 if (!myextra)
4989 return false;
4990 *myextra = rttg;
4991 *extra = myextra;
4992
4993 return true;
4994}
4995
4996/*
4997 * GUC assign_hook for recovery_target_timeline
4998 */
4999void
5008
5009/*
5010 * GUC check_hook for recovery_target_xid
5011 */
5012bool
5014{
5015 if (strcmp(*newval, "") != 0)
5016 {
5017 TransactionId xid;
5019 char *endp;
5020 char *val;
5021
5022 errno = 0;
5023
5024 /*
5025 * Consume leading whitespace to determine if number is negative
5026 */
5027 val = *newval;
5028
5029 while (isspace((unsigned char) *val))
5030 val++;
5031
5032 /*
5033 * This cast will remove the epoch, if any
5034 */
5035 xid = (TransactionId) strtou64(val, &endp, 0);
5036
5037 if (*endp != '\0' || errno == EINVAL || errno == ERANGE || *val == '-')
5038 {
5039 GUC_check_errdetail("\"%s\" is not a valid number.",
5040 "recovery_target_xid");
5041 return false;
5042 }
5043
5044 if (xid < FirstNormalTransactionId)
5045 {
5046 GUC_check_errdetail("\"%s\" without epoch must be greater than or equal to %u.",
5047 "recovery_target_xid",
5049 return false;
5050 }
5051
5053 if (!myextra)
5054 return false;
5055 *myextra = xid;
5056 *extra = myextra;
5057 }
5058 return true;
5059}
5060
5061/*
5062 * GUC assign_hook for recovery_target_xid
5063 */
5064void
5065assign_recovery_target_xid(const char *newval, void *extra)
5066{
5067 if (newval && strcmp(newval, "") != 0)
5068 recoveryTargetXid = *((TransactionId *) extra);
5069}
List * readTimeLineHistory(TimeLineID targetTLI)
Definition timeline.c:77
TimeLineID findNewestTimeLine(TimeLineID startTLI)
Definition timeline.c:265
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
Definition timeline.c:545
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition timeline.c:573
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition timeline.c:223
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
Definition timeline.c:51
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition timeline.c:527
void remove_tablespace_symlink(const char *linkloc)
Definition tablespace.c:891
bool allow_in_place_tablespaces
Definition tablespace.c:87
void disable_startup_progress_timeout(void)
Definition startup.c:308
bool IsPromoteSignaled(void)
Definition startup.c:287
void begin_startup_progress_phase(void)
Definition startup.c:342
void ProcessStartupProcInterrupts(void)
Definition startup.c:154
void ResetPromoteSignaled(void)
Definition startup.c:293
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition datetime.c:775
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition datetime.c:1000
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.c:1765
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition timestamp.c:2015
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1789
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition timestamp.c:414
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1649
const char * timestamptz_to_str(TimestampTz t)
Definition timestamp.c:1870
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1613
uint32 BlockNumber
Definition block.h:31
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5626
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
@ BUFFER_LOCK_EXCLUSIVE
Definition bufmgr.h:222
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:334
@ RBM_NORMAL_NO_LOG
Definition bufmgr.h:52
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
PageData * Page
Definition bufpage.h:81
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:410
uint8_t uint8
Definition c.h:681
#define PG_UINT32_MAX
Definition c.h:733
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:308
#define Assert(condition)
Definition c.h:1002
#define PG_BINARY
Definition c.h:1431
#define UINT64_FORMAT
Definition c.h:694
int32_t int32
Definition c.h:679
uint64_t uint64
Definition c.h:684
uint32_t uint32
Definition c.h:683
#define pg_fallthrough
Definition c.h:220
uint32 TransactionId
Definition c.h:795
size_t Size
Definition c.h:748
void RequestCheckpoint(int flags)
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
int64 TimestampTz
Definition timestamp.h:39
int32 fsec_t
Definition timestamp.h:41
Datum arg
Definition elog.c:1323
int errcode_for_file_access(void)
Definition elog.c:898
ErrorContextCallback * error_context_stack
Definition elog.c:100
int errcode(int sqlerrcode)
Definition elog.c:875
#define LOG
Definition elog.h:32
#define errcontext
Definition elog.h:200
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define FATAL
Definition elog.h:42
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define DEBUG2
Definition elog.h:30
#define PANIC
Definition elog.h:44
#define DEBUG1
Definition elog.h:31
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition fd.c:1112
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition fd.c:783
int BasicOpenFile(const char *fileName, int fileFlags)
Definition fd.c:1090
int FreeFile(FILE *file)
Definition fd.c:2827
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2957
int pg_fsync(int fd)
Definition fd.c:390
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2628
#define palloc_object(type)
Definition fe_memutils.h:89
#define palloc0_object(type)
Definition fe_memutils.h:90
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition file_utils.c:547
@ PGFILETYPE_LNK
Definition file_utils.h:24
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:692
bool IsUnderPostmaster
Definition globals.c:122
char * DataDir
Definition globals.c:73
bool IsPostmasterEnvironment
Definition globals.c:121
void GUC_check_errcode(int sqlerrcode)
Definition guc.c:6666
void * guc_malloc(int elevel, size_t size)
Definition guc.c:637
#define newval
#define GUC_check_errdetail
Definition guc.h:508
GucSource
Definition guc.h:112
#define GUC_check_errhint
Definition guc.h:512
const char * str
#define MAXDATEFIELDS
Definition datetime.h:202
#define DTK_DATE
Definition datetime.h:144
#define MAXDATELEN
Definition datetime.h:200
long val
Definition informix.c:689
#define close(a)
Definition win32.h:12
void proc_exit(int code)
Definition ipc.c:105
int i
Definition isn.c:77
void OwnLatch(Latch *latch)
Definition latch.c:126
void DisownLatch(Latch *latch)
Definition latch.c:144
void InitSharedLatch(Latch *latch)
Definition latch.c:93
void SetLatch(Latch *latch)
Definition latch.c:290
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
List * lappend(List *list, void *datum)
Definition list.c:339
void list_free_deep(List *list)
Definition list.c:1560
static struct pg_tm tm
Definition localtime.c:148
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc(Size size)
Definition mcxt.c:1390
#define AmStartupProcess()
Definition miscadmin.h:396
#define IsBootstrapProcessingMode()
Definition miscadmin.h:486
static char * errmsg
#define ERRCODE_DATA_CORRUPTED
#define MAXPGPATH
#define XLOG_RESTORE_POINT
Definition pg_control.h:79
#define XLOG_CHECKPOINT_REDO
Definition pg_control.h:86
#define XLOG_OVERWRITE_CONTRECORD
Definition pg_control.h:85
DBState
Definition pg_control.h:98
@ DB_IN_ARCHIVE_RECOVERY
Definition pg_control.h:104
@ DB_SHUTDOWNED_IN_RECOVERY
Definition pg_control.h:101
@ DB_SHUTDOWNED
Definition pg_control.h:100
@ DB_IN_CRASH_RECOVERY
Definition pg_control.h:103
#define XLOG_CHECKPOINT_SHUTDOWN
Definition pg_control.h:72
#define XLOG_BACKUP_END
Definition pg_control.h:77
#define XLOG_CHECKPOINT_ONLINE
Definition pg_control.h:73
#define XLOG_END_OF_RECOVERY
Definition pg_control.h:81
const void size_t len
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
XLogRecPtr pg_lsn_in_safe(const char *str, Node *escontext)
Definition pg_lsn.c:32
static rewind_source * source
Definition pg_rewind.c:89
const char * pg_rusage_show(const PGRUsage *ru0)
Definition pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition pg_rusage.c:27
static char buf[DEFAULT_XLOG_SEG_SIZE]
@ IOOBJECT_WAL
Definition pgstat.h:283
@ IOCONTEXT_NORMAL
Definition pgstat.h:293
@ IOOP_READ
Definition pgstat.h:319
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition pgstat_io.c:91
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition pgstat_io.c:122
int64 timestamp
void SendPostmasterSignal(PMSignalReason reason)
Definition pmsignal.c:164
@ PMSIGNAL_RECOVERY_STARTED
Definition pmsignal.h:35
@ PMSIGNAL_BEGIN_HOT_STANDBY
Definition pmsignal.h:37
@ PMSIGNAL_RECOVERY_CONSISTENT
Definition pmsignal.h:36
#define pg_pread
Definition port.h:248
#define snprintf
Definition port.h:261
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
off_t pgoff_t
Definition port.h:422
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
static int fd(const char *x, int i)
static int fb(int x)
#define EINVAL
Definition private.h:69
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition procarray.c:4443
void KnownAssignedTransactionIdsIdleMaintenance(void)
Definition procarray.c:4604
static void set_ps_display(const char *activity)
Definition ps_status.h:40
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
ForkNumber
Definition relpath.h:56
@ MAIN_FORKNUM
Definition relpath.h:58
#define PG_TBLSPC_DIR
Definition relpath.h:41
void RmgrStartup(void)
Definition rmgr.c:58
void RmgrCleanup(void)
Definition rmgr.c:74
#define ShmemRequestStruct(...)
Definition shmem.h:176
bool ReplicationSlotValidateNameInternal(const char *name, bool allow_reserved_name, int *err_code, char **err_msg, char **err_hint)
Definition slot.c:310
void ShutDownSlotSync(void)
Definition slotsync.c:1830
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56
static void SpinLockInit(volatile slock_t *lock)
Definition spin.h:50
#define ereport_startup_progress(msg,...)
Definition startup.h:18
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
Oid oldestMultiDB
Definition pg_control.h:52
MultiXactId oldestMulti
Definition pg_control.h:51
MultiXactOffset nextMultiOffset
Definition pg_control.h:48
TransactionId newestCommitTsXid
Definition pg_control.h:56
TransactionId oldestXid
Definition pg_control.h:49
TimeLineID PrevTimeLineID
Definition pg_control.h:40
TimeLineID ThisTimeLineID
Definition pg_control.h:39
MultiXactId nextMulti
Definition pg_control.h:47
FullTransactionId nextXid
Definition pg_control.h:45
TransactionId oldestCommitTsXid
Definition pg_control.h:54
XLogRecPtr redo
Definition pg_control.h:37
Oid oldestXidDB
Definition pg_control.h:50
XLogRecPtr backupStartPoint
Definition pg_control.h:178
CheckPoint checkPointCopy
Definition pg_control.h:143
XLogRecPtr backupEndPoint
Definition pg_control.h:179
XLogRecPtr minRecoveryPoint
Definition pg_control.h:176
XLogRecPtr checkPoint
Definition pg_control.h:141
uint64 system_identifier
Definition pg_control.h:118
TimeLineID minRecoveryPointTLI
Definition pg_control.h:177
Definition dirent.c:26
struct ErrorContextCallback * previous
Definition elog.h:299
void(* callback)(void *arg)
Definition elog.h:300
Definition pg_list.h:54
Definition nodes.h:133
RelFileNumber relNumber
void(* rm_redo)(XLogReaderState *record)
ShmemRequestCallback request_fn
Definition shmem.h:133
TimeLineID ws_tli
Definition xlogreader.h:49
XLogRecPtr missingContrecPtr
Definition xlogreader.h:214
char * errormsg_buf
Definition xlogreader.h:310
XLogRecPtr EndRecPtr
Definition xlogreader.h:206
uint64 system_identifier
Definition xlogreader.h:190
XLogRecPtr ReadRecPtr
Definition xlogreader.h:205
XLogRecPtr abortedRecPtr
Definition xlogreader.h:213
TimeLineID latestPageTLI
Definition xlogreader.h:279
XLogRecPtr overwrittenRecPtr
Definition xlogreader.h:216
XLogRecPtr latestPagePtr
Definition xlogreader.h:278
WALOpenSegment seg
Definition xlogreader.h:271
void * private_data
Definition xlogreader.h:195
uint8 xl_info
Definition xlogrecord.h:46
uint32 xl_tot_len
Definition xlogrecord.h:43
TransactionId xl_xid
Definition xlogrecord.h:44
RmgrId xl_rmid
Definition xlogrecord.h:47
ConditionVariable recoveryNotPausedCV
XLogRecPtr lastReplayedEndRecPtr
TimeLineID replayEndTLI
TimeLineID lastReplayedTLI
TimestampTz currentChunkStartTime
XLogRecPtr replayEndRecPtr
TimestampTz recoveryLastXTime
RecoveryPauseState recoveryPauseState
XLogRecPtr lastReplayedReadRecPtr
Definition guc.h:174
Definition pgtime.h:35
#define InvalidTransactionId
Definition transam.h:31
#define U64FromFullTransactionId(x)
Definition transam.h:49
#define XidFromFullTransactionId(x)
Definition transam.h:48
#define FirstNormalTransactionId
Definition transam.h:34
#define TransactionIdIsValid(xid)
Definition transam.h:41
#define TransactionIdIsNormal(xid)
Definition transam.h:42
#define TimestampTzPlusMilliseconds(tz, ms)
Definition timestamp.h:85
static TimestampTz DatumGetTimestampTz(Datum X)
Definition timestamp.h:34
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition varsup.c:299
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:67
static void pgstat_report_wait_end(void)
Definition wait_event.h:83
const char * name
#define WL_TIMEOUT
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET
void WalRcvRequestApplyReply(void)
#define AllowCascadeReplication()
Definition walreceiver.h:40
@ WALRCV_STOPPING
Definition walreceiver.h:54
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
bool WalRcvStreaming(void)
void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, const char *slotname, bool create_temp_slot)
WalRcvState WalRcvGetState(void)
bool WalRcvRunning(void)
void WalSndWakeup(bool physical, bool logical)
Definition walsender.c:4050
#define stat
Definition win32_port.h:74
#define S_IRUSR
Definition win32_port.h:296
#define symlink(oldpath, newpath)
Definition win32_port.h:242
#define S_IWUSR
Definition win32_port.h:299
#define XLOG_XACT_COMMIT_PREPARED
Definition xact.h:173
#define XLOG_XACT_COMMIT
Definition xact.h:170
#define XLOG_XACT_OPMASK
Definition xact.h:180
#define XLOG_XACT_ABORT
Definition xact.h:172
#define XLOG_XACT_ABORT_PREPARED
Definition xact.h:174
void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
Definition xactdesc.c:35
void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
Definition xactdesc.c:141
int wal_decode_buffer_size
Definition xlog.c:143
bool EnableHotStandby
Definition xlog.c:128
XLogRecPtr GetRedoRecPtr(void)
Definition xlog.c:6938
void SetInstallXLogFileSegmentActive(void)
Definition xlog.c:10159
bool IsInstallXLogFileSegmentActive(void)
Definition xlog.c:10176
int wal_segment_size
Definition xlog.c:150
void SwitchIntoArchiveRecovery(XLogRecPtr EndRecPtr, TimeLineID replayTLI)
Definition xlog.c:6710
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition xlog.c:3990
void ReachedEndOfBackup(XLogRecPtr EndRecPtr, TimeLineID tli)
Definition xlog.c:6748
void ResetInstallXLogFileSegmentActive(void)
Definition xlog.c:10168
int wal_retrieve_retry_interval
Definition xlog.c:141
bool track_wal_io_timing
Definition xlog.c:144
static ControlFileData * ControlFile
Definition xlog.c:584
void XLogShutdownWalRcv(void)
Definition xlog.c:10149
bool XLogCheckpointNeeded(XLogSegNo new_segno)
Definition xlog.c:2301
#define TABLESPACE_MAP_OLD
Definition xlog.h:338
#define TABLESPACE_MAP
Definition xlog.h:337
#define STANDBY_SIGNAL_FILE
Definition xlog.h:333
#define CHECKPOINT_CAUSE_XLOG
Definition xlog.h:160
#define PROMOTE_SIGNAL_FILE
Definition xlog.h:341
#define BACKUP_LABEL_FILE
Definition xlog.h:334
#define RECOVERY_SIGNAL_FILE
Definition xlog.h:332
static RmgrData GetRmgr(RmgrId rmid)
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
#define MAXFNAMELEN
#define XLOGDIR
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
static void XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
#define XRecOffIsValid(xlrp)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition xlogarchive.c:55
void KeepFileRestoredFromArchive(const char *path, const char *xlogfname)
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
uint64 XLogRecPtr
Definition xlogdefs.h:21
#define InvalidXLogRecPtr
Definition xlogdefs.h:28
uint32 TimeLineID
Definition xlogdefs.h:63
uint64 XLogSegNo
Definition xlogdefs.h:52
void XLogPrefetcherComputeStats(XLogPrefetcher *prefetcher)
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
void XLogPrefetchReconfigure(void)
XLogRecord * XLogPrefetcherReadRecord(XLogPrefetcher *prefetcher, char **errmsg)
XLogReaderState * XLogPrefetcherGetReader(XLogPrefetcher *prefetcher)
void XLogPrefetcherBeginRead(XLogPrefetcher *prefetcher, XLogRecPtr recPtr)
void XLogPrefetcherFree(XLogPrefetcher *prefetcher)
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition xlogreader.c:108
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition xlogreader.c:92
void XLogReaderResetError(XLogReaderState *state)
bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr)
void XLogReaderFree(XLogReaderState *state)
Definition xlogreader.c:163
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
#define XLogRecGetDataLen(decoder)
Definition xlogreader.h:416
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:410
#define XLogRecBlockImageApply(decoder, block_id)
Definition xlogreader.h:425
#define XLogRecGetRmid(decoder)
Definition xlogreader.h:411
#define XLogRecGetData(decoder)
Definition xlogreader.h:415
#define XLogRecGetXid(decoder)
Definition xlogreader.h:412
#define XL_ROUTINE(...)
Definition xlogreader.h:117
#define XLogRecMaxBlockId(decoder)
Definition xlogreader.h:418
XLogPageReadResult
Definition xlogreader.h:350
@ XLREAD_WOULDBLOCK
Definition xlogreader.h:353
@ XLREAD_SUCCESS
Definition xlogreader.h:351
@ XLREAD_FAIL
Definition xlogreader.h:352
#define XLogRecHasBlockImage(decoder, block_id)
Definition xlogreader.h:423
#define XLogRecGetPrev(decoder)
Definition xlogreader.h:409
#define XLogRecHasAnyBlockRefs(decoder)
Definition xlogreader.h:417
#define SizeOfXLogRecordDataHeaderShort
Definition xlogrecord.h:217
#define XLR_INFO_MASK
Definition xlogrecord.h:62
#define SizeOfXLogRecord
Definition xlogrecord.h:55
#define XLR_CHECK_CONSISTENCY
Definition xlogrecord.h:91
bool reachedConsistency
bool check_primary_slot_name(char **newval, void **extra, GucSource source)
static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime)
static XLogRecPtr recoveryStopLSN
static bool recoveryStopsBefore(XLogReaderState *record)
static TimestampTz recoveryStopTime
void assign_recovery_target_xid(const char *newval, void *extra)
static bool CheckForStandbyTrigger(void)
int recovery_min_apply_delay
bool check_recovery_target(char **newval, void **extra, GucSource source)
static bool backupEndRequired
bool HotStandbyActive(void)
static char * getRecoveryStopReason(void)
void ShutdownWalRecovery(void)
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
int recoveryTargetAction
static void rm_redo_error_callback(void *arg)
static bool recoveryApplyDelay(XLogReaderState *record)
bool ArchiveRecoveryRequested
static void xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI)
bool check_recovery_target_timeline(char **newval, void **extra, GucSource source)
static XLogRecPtr minRecoveryPoint
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static XLogRecPtr backupEndPoint
const struct config_enum_entry recovery_target_action_options[]
static void validateRecoveryParameters(void)
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI, TimeLineID replayTLI)
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
void StartupRequestWalReceiverRestart(void)
bool InArchiveRecovery
static bool recoveryStopsAfter(XLogReaderState *record)
void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue)
char * PrimarySlotName
static TimeLineID curFileTLI
static char recoveryStopName[MAXFNAMELEN]
static void CheckRecoveryConsistency(void)
static bool pendingWalRcvRestart
void PerformWalRecovery(void)
static XLogSource XLogReceiptSource
bool CheckPromoteSignal(void)
struct XLogPageReadPrivate XLogPageReadPrivate
static bool recoveryStopAfter
static const char *const xlogSourceNames[]
static TimeLineID RedoStartTLI
char * recoveryRestoreCommand
static void verifyBackupPageConsistency(XLogReaderState *record)
static int XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source)
void SetRecoveryPause(bool recoveryPause)
static bool lastSourceFailed
char * archiveCleanupCommand
XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI)
const ShmemCallbacks XLogRecoveryShmemCallbacks
static TimeLineID receiveTLI
void WakeupRecovery(void)
void xlog_outdesc(StringInfo buf, XLogReaderState *record)
static bool LocalPromoteIsTriggered
bool PromoteIsTriggered(void)
TimestampTz GetCurrentChunkReplayStartTime(void)
static void ConfirmRecoveryPaused(void)
static void readRecoverySignalFile(void)
static XLogRecPtr missingContrecPtr
XLogRecoveryCtlData * XLogRecoveryCtl
static uint32 readOff
static bool standby_signal_file_found
char * recovery_target_time_string
bool StandbyMode
static int readFile
static XLogPageReadResult WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr, TimeLineID replayTLI, XLogRecPtr replayLSN, bool nonblocking)
XLogRecPtr recoveryTargetLSN
RecoveryTargetType recoveryTarget
static bool read_tablespace_map(List **tablespaces)
static bool doRequestWalReceiverReply
static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
static int XLogFileRead(XLogSegNo segno, TimeLineID tli, XLogSource source, bool notfoundOk)
static XLogSource currentSource
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
void GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream)
static List * expectedTLEs
static XLogSegNo readSegNo
static XLogRecPtr abortedRecPtr
static char * primary_image_masked
static TimeLineID minRecoveryPointTLI
static XLogRecord * ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI)
EndOfWalRecoveryInfo * FinishWalRecovery(void)
static void SetCurrentChunkStartTime(TimestampTz xtime)
static XLogRecPtr CheckPointLoc
bool check_recovery_target_xid(char **newval, void **extra, GucSource source)
static bool LocalHotStandbyActive
static bool HotStandbyActiveInReplay(void)
static bool InRedo
static TransactionId recoveryStopXid
bool check_recovery_target_time(char **newval, void **extra, GucSource source)
static RecoveryTargetType DetermineRecoveryTargetType(void)
static XLogSource readSource
static void SetPromoteIsTriggered(void)
#define RECOVERY_COMMAND_FILE
TransactionId recoveryTargetXid
XLogSource
@ XLOG_FROM_PG_WAL
@ XLOG_FROM_STREAM
@ XLOG_FROM_ARCHIVE
@ XLOG_FROM_ANY
TimeLineID recoveryTargetTLIRequested
void InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
static void xlog_block_info(StringInfo buf, XLogReaderState *record)
static TimestampTz XLogReceiptTime
static void XLogRecoveryShmemInit(void *arg)
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
static char * replay_image_masked
#define ADD_TARGET_IF_SET(gucname, kind)
bool wal_receiver_create_temp_slot
static void CheckTablespaceDirectory(void)
char * recoveryEndCommand
RecoveryPauseState GetRecoveryPauseState(void)
TimeLineID recoveryTargetTLI
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
void assign_recovery_target_lsn(const char *newval, void *extra)
bool check_recovery_target_lsn(char **newval, void **extra, GucSource source)
static XLogRecPtr RedoStartLSN
static XLogRecPtr flushedUpto
static void recoveryPausesHere(bool endOfRecovery)
static uint32 readLen
static void EnableStandbyMode(void)
#define RECOVERY_COMMAND_DONE
static bool recovery_signal_file_found
TimestampTz recoveryTargetTime
TimestampTz GetLatestXTime(void)
char * recoveryTargetName
char * PrimaryConnInfo
void XLogRequestWalReceiverReply(void)
static bool rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN)
static XLogPrefetcher * xlogprefetcher
static bool StandbyModeRequested
bool check_recovery_target_name(char **newval, void **extra, GucSource source)
bool recoveryTargetInclusive
static XLogReaderState * xlogreader
void RemovePromoteSignalFiles(void)
void assign_recovery_target_timeline(const char *newval, void *extra)
static XLogRecPtr backupStartPoint
static void SetLatestXTime(TimestampTz xtime)
static TimeLineID CheckPointTLI
static void XLogRecoveryShmemRequest(void *arg)
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
RecoveryTargetType
@ RECOVERY_TARGET_IMMEDIATE
@ RECOVERY_TARGET_TIME
@ RECOVERY_TARGET_UNSET
@ RECOVERY_TARGET_XID
@ RECOVERY_TARGET_LSN
@ RECOVERY_TARGET_NAME
RecoveryTargetTimeLineGoal
@ RECOVERY_TARGET_TIMELINE_NUMERIC
@ RECOVERY_TARGET_TIMELINE_CONTROLFILE
@ RECOVERY_TARGET_TIMELINE_LATEST
RecoveryPauseState
@ RECOVERY_PAUSED
@ RECOVERY_NOT_PAUSED
@ RECOVERY_PAUSE_REQUESTED
void wal_segment_close(XLogReaderState *state)
Definition xlogutils.c:855
Buffer XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)
Definition xlogutils.c:484
HotStandbyState standbyState
Definition xlogutils.c:53
bool InRecovery
Definition xlogutils.c:50
void XLogCheckInvalidPages(void)
Definition xlogutils.c:234
@ STANDBY_SNAPSHOT_READY
Definition xlogutils.h:55
@ STANDBY_INITIALIZED
Definition xlogutils.h:53
void WaitLSNWakeup(WaitLSNType lsnType, XLogRecPtr currentLSN)
Definition xlogwait.c:344
@ WAIT_LSN_TYPE_STANDBY_REPLAY
Definition xlogwait.h:39
@ WAIT_LSN_TYPE_STANDBY_FLUSH
Definition xlogwait.h:41
@ WAIT_LSN_TYPE_STANDBY_WRITE
Definition xlogwait.h:40