#include "access/xlogdefs.h"#include "datatype/timestamp.h"#include "lib/stringinfo.h"#include "pgtime.h"#include "storage/block.h"#include "storage/relfilenode.h"

Go to the source code of this file.
Data Structures | |
| struct | BkpBlock |
| struct | XLogPageHeaderData |
| struct | XLogLongPageHeaderData |
| struct | xl_parameter_change |
| struct | xl_restore_point |
| struct | xl_end_of_recovery |
| struct | RmgrData |
Defines | |
| #define | XLOG_PAGE_MAGIC 0xD075 |
| #define | SizeOfXLogShortPHD MAXALIGN(sizeof(XLogPageHeaderData)) |
| #define | SizeOfXLogLongPHD MAXALIGN(sizeof(XLogLongPageHeaderData)) |
| #define | XLP_FIRST_IS_CONTRECORD 0x0001 |
| #define | XLP_LONG_HEADER 0x0002 |
| #define | XLP_BKP_REMOVABLE 0x0004 |
| #define | XLP_ALL_FLAGS 0x0007 |
| #define | XLogPageHeaderSize(hdr) (((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD) |
| #define | XLogSegSize ((uint32) XLOG_SEG_SIZE) |
| #define | XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLOG_SEG_SIZE) |
| #define | XLogSegNoOffsetToRecPtr(segno, offset, dest) (dest) = (segno) * XLOG_SEG_SIZE + (offset) |
| #define | XLByteToSeg(xlrp, logSegNo) logSegNo = (xlrp) / XLogSegSize |
| #define | XLByteToPrevSeg(xlrp, logSegNo) logSegNo = ((xlrp) - 1) / XLogSegSize |
| #define | XLByteInSeg(xlrp, logSegNo) (((xlrp) / XLogSegSize) == (logSegNo)) |
| #define | XLByteInPrevSeg(xlrp, logSegNo) ((((xlrp) - 1) / XLogSegSize) == (logSegNo)) |
| #define | XRecOffIsValid(xlrp) ((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD) |
| #define | XLOGDIR "pg_xlog" |
| #define | XLOG_CONTROL_FILE "global/pg_control" |
| #define | MAXFNAMELEN 64 |
| #define | XLogFileName(fname, tli, logSegNo) |
| #define | XLogFromFileName(fname, tli, logSegNo) |
| #define | XLogFilePath(path, tli, logSegNo) |
| #define | TLHistoryFileName(fname, tli) snprintf(fname, MAXFNAMELEN, "%08X.history", tli) |
| #define | TLHistoryFilePath(path, tli) snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli) |
| #define | StatusFilePath(path, xlog, suffix) snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix) |
| #define | BackupHistoryFileName(fname, tli, logSegNo, offset) |
| #define | BackupHistoryFilePath(path, tli, logSegNo, offset) |
Typedefs | |
| typedef struct BkpBlock | BkpBlock |
| typedef struct XLogPageHeaderData | XLogPageHeaderData |
| typedef XLogPageHeaderData * | XLogPageHeader |
| typedef struct XLogLongPageHeaderData | XLogLongPageHeaderData |
| typedef XLogLongPageHeaderData * | XLogLongPageHeader |
| typedef struct xl_parameter_change | xl_parameter_change |
| typedef struct xl_restore_point | xl_restore_point |
| typedef struct xl_end_of_recovery | xl_end_of_recovery |
| typedef struct RmgrData | RmgrData |
Functions | |
| pg_time_t | GetLastSegSwitchTime (void) |
| XLogRecPtr | RequestXLogSwitch (void) |
| void | GetOldestRestartPoint (XLogRecPtr *oldrecptr, TimeLineID *oldtli) |
| bool | RestoreArchivedFile (char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled) |
| void | ExecuteRecoveryCommand (char *command, char *commandName, bool failOnerror) |
| void | KeepFileRestoredFromArchive (char *path, char *xlogfname) |
| void | XLogArchiveNotify (const char *xlog) |
| void | XLogArchiveNotifySeg (XLogSegNo segno) |
| void | XLogArchiveForceDone (const char *xlog) |
| bool | XLogArchiveCheckDone (const char *xlog) |
| bool | XLogArchiveIsBusy (const char *xlog) |
| void | XLogArchiveCleanup (const char *xlog) |
Variables | |
| const RmgrData | RmgrTable [] |
| bool | ArchiveRecoveryRequested |
| bool | InArchiveRecovery |
| bool | StandbyMode |
| char * | recoveryRestoreCommand |
| #define BackupHistoryFileName | ( | fname, | ||
| tli, | ||||
| logSegNo, | ||||
| offset | ||||
| ) |
snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli, \ (uint32) ((logSegNo) / XLogSegmentsPerXLogId), \ (uint32) ((logSegNo) % XLogSegmentsPerXLogId), offset)
Definition at line 191 of file xlog_internal.h.
Referenced by do_pg_stop_backup().
| #define BackupHistoryFilePath | ( | path, | ||
| tli, | ||||
| logSegNo, | ||||
| offset | ||||
| ) |
snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli, \ (uint32) ((logSegNo) / XLogSegmentsPerXLogId), \ (uint32) ((logSegNo) % XLogSegmentsPerXLogId), offset)
Definition at line 196 of file xlog_internal.h.
Referenced by do_pg_stop_backup().
| #define MAXFNAMELEN 64 |
Definition at line 162 of file xlog_internal.h.
Referenced by pg_create_restore_point(), pgarch_archiveXlog(), readRecoveryCommandFile(), recoveryStopsHere(), XLogFileNameP(), XLogFileRead(), and XLogRestorePoint().
| #define SizeOfXLogLongPHD MAXALIGN(sizeof(XLogLongPageHeaderData)) |
Definition at line 96 of file xlog_internal.h.
Referenced by RewriteControlFile(), and XLogInsert().
| #define SizeOfXLogShortPHD MAXALIGN(sizeof(XLogPageHeaderData)) |
Definition at line 79 of file xlog_internal.h.
Referenced by ReadPageInternal(), and XLogReadRecord().
| #define StatusFilePath | ( | path, | ||
| xlog, | ||||
| suffix | ||||
| ) | snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix) |
Definition at line 188 of file xlog_internal.h.
Referenced by pgarch_archiveDone(), XLogArchiveCheckDone(), XLogArchiveCleanup(), XLogArchiveForceDone(), XLogArchiveIsBusy(), and XLogArchiveNotify().
| #define TLHistoryFileName | ( | fname, | ||
| tli | ||||
| ) | snprintf(fname, MAXFNAMELEN, "%08X.history", tli) |
Definition at line 182 of file xlog_internal.h.
Referenced by existsTimeLineHistory(), existsTimeLineHistoryFile(), readTimeLineHistory(), restoreTimeLineHistoryFiles(), SendTimeLineHistory(), WalRcvFetchTimeLineHistoryFiles(), writeTimeLineHistory(), and writeTimeLineHistoryFile().
| #define TLHistoryFilePath | ( | path, | ||
| tli | ||||
| ) | snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli) |
Definition at line 185 of file xlog_internal.h.
Referenced by existsTimeLineHistory(), readTimeLineHistory(), SendTimeLineHistory(), writeTimeLineHistory(), and writeTimeLineHistoryFile().
| #define XLByteInPrevSeg | ( | xlrp, | ||
| logSegNo | ||||
| ) | ((((xlrp) - 1) / XLogSegSize) == (logSegNo)) |
Definition at line 145 of file xlog_internal.h.
Referenced by XLogBackgroundFlush(), and XLogWrite().
| #define XLByteInSeg | ( | xlrp, | ||
| logSegNo | ||||
| ) | (((xlrp) / XLogSegSize) == (logSegNo)) |
Definition at line 142 of file xlog_internal.h.
Referenced by main(), XLogDumpXLogRead(), XLogPageRead(), XLogRead(), and XLogWalRcvWrite().
| #define XLByteToPrevSeg | ( | xlrp, | ||
| logSegNo | ||||
| ) | logSegNo = ((xlrp) - 1) / XLogSegSize |
Definition at line 133 of file xlog_internal.h.
Referenced by do_pg_stop_backup(), perform_base_backup(), pg_xlogfile_name(), pg_xlogfile_name_offset(), PreallocXlogFiles(), RemoveOldXlogFiles(), StartupXLOG(), and XLogWrite().
| #define XLByteToSeg | ( | xlrp, | ||
| logSegNo | ||||
| ) | logSegNo = (xlrp) / XLogSegSize |
Definition at line 130 of file xlog_internal.h.
Referenced by CreateCheckPoint(), CreateRestartPoint(), do_pg_start_backup(), do_pg_stop_backup(), ExecuteRecoveryCommand(), KeepLogSeg(), main(), open_walfile(), perform_base_backup(), ReadPageInternal(), ReadRecord(), RestoreArchivedFile(), ValidXLogPageHeader(), XLogCheckpointNeeded(), XLogDumpXLogRead(), XLogPageRead(), XLogRead(), and XLogWalRcvWrite().
| #define XLOG_CONTROL_FILE "global/pg_control" |
Definition at line 156 of file xlog_internal.h.
Referenced by perform_base_backup(), ReadControlFile(), RewriteControlFile(), UpdateControlFile(), and WriteControlFile().
| #define XLOG_PAGE_MAGIC 0xD075 |
Definition at line 58 of file xlog_internal.h.
Referenced by ValidXLogPageHeader().
| #define XLOGDIR "pg_xlog" |
Definition at line 155 of file xlog_internal.h.
Referenced by CleanupBackupHistory(), exitArchiveRecovery(), FindEndOfXLOG(), fuzzy_open_file(), KeepFileRestoredFromArchive(), KillExistingXLOG(), perform_base_backup(), pgarch_archiveXlog(), pgarch_readyXlog(), RemoveOldXlogFiles(), RestoreArchivedFile(), ValidateXLOGDirectoryStructure(), writeTimeLineHistory(), writeTimeLineHistoryFile(), XLogArchiveIsBusy(), XLogFileCopy(), XLogFileInit(), and XLogFileRead().
| #define XLogFileName | ( | fname, | ||
| tli, | ||||
| logSegNo | ||||
| ) |
snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, \ (uint32) ((logSegNo) / XLogSegmentsPerXLogId), \ (uint32) ((logSegNo) % XLogSegmentsPerXLogId))
Definition at line 164 of file xlog_internal.h.
| #define XLogFilePath | ( | path, | ||
| tli, | ||||
| logSegNo | ||||
| ) |
snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli, \ (uint32) ((logSegNo) / XLogSegmentsPerXLogId), \ (uint32) ((logSegNo) % XLogSegmentsPerXLogId))
Definition at line 177 of file xlog_internal.h.
Referenced by InstallXLogFileSegment(), WriteEmptyXLOG(), XLogFileCopy(), XLogFileInit(), XLogFileOpen(), XLogFileRead(), XLogFileReadAnyTLI(), and XLogRead().
| #define XLogFromFileName | ( | fname, | ||
| tli, | ||||
| logSegNo | ||||
| ) |
do { \ uint32 log; \ uint32 seg; \ sscanf(fname, "%08X%08X%08X", tli, &log, &seg); \ *logSegNo = (uint64) log * XLogSegmentsPerXLogId + seg; \ } while (0)
Definition at line 169 of file xlog_internal.h.
Referenced by main(), perform_base_backup(), and UpdateLastRemovedPtr().
| #define XLogPageHeaderSize | ( | hdr | ) | (((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD) |
Definition at line 109 of file xlog_internal.h.
Referenced by ReadPageInternal(), and XLogReadRecord().
| #define XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLOG_SEG_SIZE) |
Definition at line 117 of file xlog_internal.h.
| #define XLogSegNoOffsetToRecPtr | ( | segno, | ||
| offset, | ||||
| dest | ||||
| ) | (dest) = (segno) * XLOG_SEG_SIZE + (offset) |
Definition at line 119 of file xlog_internal.h.
Referenced by FindStreamingStart(), main(), RewriteControlFile(), and ValidXLogPageHeader().
| #define XLogSegSize ((uint32) XLOG_SEG_SIZE) |
Definition at line 116 of file xlog_internal.h.
Referenced by AdvanceXLInsertBuffer(), BootStrapXLOG(), CheckArchiveTimeout(), do_pg_stop_backup(), FindEndOfXLOG(), IsCheckpointOnSchedule(), main(), open_walfile(), perform_base_backup(), PreallocXlogFiles(), RequestXLogStreaming(), StartupXLOG(), ValidXLogPageHeader(), XLogDumpXLogRead(), XLogFileRead(), XLogInsert(), XLogPageRead(), XLogRead(), XLogReadRecord(), XLogWalRcvWrite(), and XLogWrite().
| #define XLP_ALL_FLAGS 0x0007 |
Definition at line 107 of file xlog_internal.h.
Referenced by ValidXLogPageHeader().
| #define XLP_BKP_REMOVABLE 0x0004 |
Definition at line 105 of file xlog_internal.h.
| #define XLP_FIRST_IS_CONTRECORD 0x0001 |
Definition at line 101 of file xlog_internal.h.
Referenced by XLogReadRecord().
| #define XLP_LONG_HEADER 0x0002 |
Definition at line 103 of file xlog_internal.h.
Referenced by ValidXLogPageHeader().
| #define XRecOffIsValid | ( | xlrp | ) | ((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD) |
Definition at line 149 of file xlog_internal.h.
Referenced by ReadCheckpointRecord(), StartupXLOG(), and XLogReadRecord().
| typedef struct xl_end_of_recovery xl_end_of_recovery |
| typedef struct xl_parameter_change xl_parameter_change |
| typedef struct xl_restore_point xl_restore_point |
| typedef XLogLongPageHeaderData* XLogLongPageHeader |
Definition at line 98 of file xlog_internal.h.
| typedef struct XLogLongPageHeaderData XLogLongPageHeaderData |
| typedef XLogPageHeaderData* XLogPageHeader |
Definition at line 81 of file xlog_internal.h.
| typedef struct XLogPageHeaderData XLogPageHeaderData |
| void ExecuteRecoveryCommand | ( | char * | command, | |
| char * | commandName, | |||
| bool | failOnerror | |||
| ) |
Definition at line 330 of file xlogarchive.c.
References Assert, DEBUG3, ereport, errmsg(), errmsg_internal(), FATAL, GetOldestRestartPoint(), MAXPGPATH, signaled, StrNCpy, system(), WARNING, WEXITSTATUS, WIFSIGNALED, XLByteToSeg, and XLogFileName.
Referenced by CreateRestartPoint(), and StartupXLOG().
{
char xlogRecoveryCmd[MAXPGPATH];
char lastRestartPointFname[MAXPGPATH];
char *dp;
char *endp;
const char *sp;
int rc;
bool signaled;
XLogSegNo restartSegNo;
XLogRecPtr restartRedoPtr;
TimeLineID restartTli;
Assert(command && commandName);
/*
* Calculate the archive file cutoff point for use during log shipping
* replication. All files earlier than this point can be deleted from the
* archive, though there is no requirement to do so.
*/
GetOldestRestartPoint(&restartRedoPtr, &restartTli);
XLByteToSeg(restartRedoPtr, restartSegNo);
XLogFileName(lastRestartPointFname, restartTli, restartSegNo);
/*
* construct the command to be executed
*/
dp = xlogRecoveryCmd;
endp = xlogRecoveryCmd + MAXPGPATH - 1;
*endp = '\0';
for (sp = command; *sp; sp++)
{
if (*sp == '%')
{
switch (sp[1])
{
case 'r':
/* %r: filename of last restartpoint */
sp++;
StrNCpy(dp, lastRestartPointFname, endp - dp);
dp += strlen(dp);
break;
case '%':
/* convert %% to a single % */
sp++;
if (dp < endp)
*dp++ = *sp;
break;
default:
/* otherwise treat the % as not special */
if (dp < endp)
*dp++ = *sp;
break;
}
}
else
{
if (dp < endp)
*dp++ = *sp;
}
}
*dp = '\0';
ereport(DEBUG3,
(errmsg_internal("executing %s \"%s\"", commandName, command)));
/*
* execute the constructed command
*/
rc = system(xlogRecoveryCmd);
if (rc != 0)
{
/*
* If the failure was due to any sort of signal, it's best to punt and
* abort recovery. See also detailed comments on signals in
* RestoreArchivedFile().
*/
signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
ereport((signaled && failOnSignal) ? FATAL : WARNING,
/*------
translator: First %s represents a recovery.conf parameter name like
"recovery_end_command", and the 2nd is the value of that parameter. */
(errmsg("%s \"%s\": return code %d", commandName,
command, rc)));
}
}
| pg_time_t GetLastSegSwitchTime | ( | void | ) |
Definition at line 6529 of file xlog.c.
References XLogCtlWrite::lastSegSwitchTime, LW_SHARED, LWLockAcquire(), LWLockRelease(), WALWriteLock, and XLogCtlData::Write.
Referenced by CheckArchiveTimeout().
{
pg_time_t result;
/* Need WALWriteLock, but shared lock is sufficient */
LWLockAcquire(WALWriteLock, LW_SHARED);
result = XLogCtl->Write.lastSegSwitchTime;
LWLockRelease(WALWriteLock);
return result;
}
| void GetOldestRestartPoint | ( | XLogRecPtr * | oldrecptr, | |
| TimeLineID * | oldtli | |||
| ) |
Definition at line 9159 of file xlog.c.
References ControlFileData::checkPointCopy, ControlFileLock, LW_SHARED, LWLockAcquire(), LWLockRelease(), CheckPoint::redo, and CheckPoint::ThisTimeLineID.
Referenced by ExecuteRecoveryCommand(), and RestoreArchivedFile().
{
LWLockAcquire(ControlFileLock, LW_SHARED);
*oldrecptr = ControlFile->checkPointCopy.redo;
*oldtli = ControlFile->checkPointCopy.ThisTimeLineID;
LWLockRelease(ControlFileLock);
}
| void KeepFileRestoredFromArchive | ( | char * | path, | |
| char * | xlogfname | |||
| ) |
Definition at line 426 of file xlogarchive.c.
References ereport, errcode_for_file_access(), errmsg(), ERROR, FATAL, MAXPGPATH, snprintf(), unlink(), WalSndRqstFileReload(), WalSndWakeup(), XLogArchiveForceDone(), and XLOGDIR.
Referenced by readTimeLineHistory(), restoreTimeLineHistoryFiles(), and XLogFileRead().
{
char xlogfpath[MAXPGPATH];
bool reload = false;
struct stat statbuf;
snprintf(xlogfpath, MAXPGPATH, XLOGDIR "/%s", xlogfname);
if (stat(xlogfpath, &statbuf) == 0)
{
char oldpath[MAXPGPATH];
#ifdef WIN32
static unsigned int deletedcounter = 1;
/*
* On Windows, if another process (e.g a walsender process) holds
* the file open in FILE_SHARE_DELETE mode, unlink will succeed,
* but the file will still show up in directory listing until the
* last handle is closed, and we cannot rename the new file in its
* place until that. To avoid that problem, rename the old file to
* a temporary name first. Use a counter to create a unique
* filename, because the same file might be restored from the
* archive multiple times, and a walsender could still be holding
* onto an old deleted version of it.
*/
snprintf(oldpath, MAXPGPATH, "%s.deleted%u",
xlogfpath, deletedcounter++);
if (rename(xlogfpath, oldpath) != 0)
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
xlogfpath, oldpath)));
}
#else
strncpy(oldpath, xlogfpath, MAXPGPATH);
#endif
if (unlink(oldpath) != 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not remove file \"%s\": %m",
xlogfpath)));
reload = true;
}
if (rename(path, xlogfpath) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
path, xlogfpath)));
/*
* Create .done file forcibly to prevent the restored segment from
* being archived again later.
*/
XLogArchiveForceDone(xlogfname);
/*
* If the existing file was replaced, since walsenders might have it
* open, request them to reload a currently-open segment. This is only
* required for WAL segments, walsenders don't hold other files open, but
* there's no harm in doing this too often, and we don't know what kind
* of a file we're dealing with here.
*/
if (reload)
WalSndRqstFileReload();
/*
* Signal walsender that new WAL has arrived. Again, this isn't necessary
* if we restored something other than a WAL segment, but it does no harm
* either.
*/
WalSndWakeup();
}
| XLogRecPtr RequestXLogSwitch | ( | void | ) |
Definition at line 7596 of file xlog.c.
References XLogRecData::buffer, XLogRecData::data, XLogRecData::len, XLogRecData::next, XLOG_SWITCH, and XLogInsert().
Referenced by CheckArchiveTimeout(), do_pg_start_backup(), do_pg_stop_backup(), pg_switch_xlog(), and ShutdownXLOG().
{
XLogRecPtr RecPtr;
XLogRecData rdata;
/* XLOG SWITCH, alone among xlog record types, has no data */
rdata.buffer = InvalidBuffer;
rdata.data = NULL;
rdata.len = 0;
rdata.next = NULL;
RecPtr = XLogInsert(RM_XLOG_ID, XLOG_SWITCH, &rdata);
return RecPtr;
}
| bool RestoreArchivedFile | ( | char * | path, | |
| const char * | xlogfname, | |||
| const char * | recovername, | |||
| off_t | expectedSize, | |||
| bool | cleanupEnabled | |||
| ) |
Definition at line 52 of file xlogarchive.c.
References Assert, DEBUG2, DEBUG3, elevel, ereport, errcode_for_file_access(), errmsg(), errmsg_internal(), FATAL, GetOldestRestartPoint(), LOG, make_native_path(), MAXPGPATH, NULL, PostRestoreCommand(), PreRestoreCommand(), proc_exit(), recoveryRestoreCommand, signaled, snprintf(), StandbyMode, StrNCpy, system(), unlink(), WEXITSTATUS, WIFSIGNALED, WTERMSIG, XLByteToSeg, XLOGDIR, and XLogFileName.
Referenced by existsTimeLineHistory(), readTimeLineHistory(), restoreTimeLineHistoryFiles(), writeTimeLineHistory(), and XLogFileRead().
{
char xlogpath[MAXPGPATH];
char xlogRestoreCmd[MAXPGPATH];
char lastRestartPointFname[MAXPGPATH];
char *dp;
char *endp;
const char *sp;
int rc;
bool signaled;
struct stat stat_buf;
XLogSegNo restartSegNo;
XLogRecPtr restartRedoPtr;
TimeLineID restartTli;
/* In standby mode, restore_command might not be supplied */
if (recoveryRestoreCommand == NULL)
goto not_available;
/*
* When doing archive recovery, we always prefer an archived log file even
* if a file of the same name exists in XLOGDIR. The reason is that the
* file in XLOGDIR could be an old, un-filled or partly-filled version
* that was copied and restored as part of backing up $PGDATA.
*
* We could try to optimize this slightly by checking the local copy
* lastchange timestamp against the archived copy, but we have no API to
* do this, nor can we guarantee that the lastchange timestamp was
* preserved correctly when we copied to archive. Our aim is robustness,
* so we elect not to do this.
*
* If we cannot obtain the log file from the archive, however, we will try
* to use the XLOGDIR file if it exists. This is so that we can make use
* of log segments that weren't yet transferred to the archive.
*
* Notice that we don't actually overwrite any files when we copy back
* from archive because the restore_command may inadvertently
* restore inappropriate xlogs, or they may be corrupt, so we may wish to
* fallback to the segments remaining in current XLOGDIR later. The
* copy-from-archive filename is always the same, ensuring that we don't
* run out of disk space on long recoveries.
*/
snprintf(xlogpath, MAXPGPATH, XLOGDIR "/%s", recovername);
/*
* Make sure there is no existing file named recovername.
*/
if (stat(xlogpath, &stat_buf) != 0)
{
if (errno != ENOENT)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m",
xlogpath)));
}
else
{
if (unlink(xlogpath) != 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not remove file \"%s\": %m",
xlogpath)));
}
/*
* Calculate the archive file cutoff point for use during log shipping
* replication. All files earlier than this point can be deleted from the
* archive, though there is no requirement to do so.
*
* If cleanup is not enabled, initialise this with the filename of
* InvalidXLogRecPtr, which will prevent the deletion of any WAL files
* from the archive because of the alphabetic sorting property of WAL
* filenames.
*
* Once we have successfully located the redo pointer of the checkpoint
* from which we start recovery we never request a file prior to the redo
* pointer of the last restartpoint. When redo begins we know that we have
* successfully located it, so there is no need for additional status
* flags to signify the point when we can begin deleting WAL files from
* the archive.
*/
if (cleanupEnabled)
{
GetOldestRestartPoint(&restartRedoPtr, &restartTli);
XLByteToSeg(restartRedoPtr, restartSegNo);
XLogFileName(lastRestartPointFname, restartTli, restartSegNo);
/* we shouldn't need anything earlier than last restart point */
Assert(strcmp(lastRestartPointFname, xlogfname) <= 0);
}
else
XLogFileName(lastRestartPointFname, 0, 0L);
/*
* construct the command to be executed
*/
dp = xlogRestoreCmd;
endp = xlogRestoreCmd + MAXPGPATH - 1;
*endp = '\0';
for (sp = recoveryRestoreCommand; *sp; sp++)
{
if (*sp == '%')
{
switch (sp[1])
{
case 'p':
/* %p: relative path of target file */
sp++;
StrNCpy(dp, xlogpath, endp - dp);
make_native_path(dp);
dp += strlen(dp);
break;
case 'f':
/* %f: filename of desired file */
sp++;
StrNCpy(dp, xlogfname, endp - dp);
dp += strlen(dp);
break;
case 'r':
/* %r: filename of last restartpoint */
sp++;
StrNCpy(dp, lastRestartPointFname, endp - dp);
dp += strlen(dp);
break;
case '%':
/* convert %% to a single % */
sp++;
if (dp < endp)
*dp++ = *sp;
break;
default:
/* otherwise treat the % as not special */
if (dp < endp)
*dp++ = *sp;
break;
}
}
else
{
if (dp < endp)
*dp++ = *sp;
}
}
*dp = '\0';
ereport(DEBUG3,
(errmsg_internal("executing restore command \"%s\"",
xlogRestoreCmd)));
/*
* Check signals before restore command and reset afterwards.
*/
PreRestoreCommand();
/*
* Copy xlog from archival storage to XLOGDIR
*/
rc = system(xlogRestoreCmd);
PostRestoreCommand();
if (rc == 0)
{
/*
* command apparently succeeded, but let's make sure the file is
* really there now and has the correct size.
*/
if (stat(xlogpath, &stat_buf) == 0)
{
if (expectedSize > 0 && stat_buf.st_size != expectedSize)
{
int elevel;
/*
* If we find a partial file in standby mode, we assume it's
* because it's just being copied to the archive, and keep
* trying.
*
* Otherwise treat a wrong-sized file as FATAL to ensure the
* DBA would notice it, but is that too strong? We could try
* to plow ahead with a local copy of the file ... but the
* problem is that there probably isn't one, and we'd
* incorrectly conclude we've reached the end of WAL and we're
* done recovering ...
*/
if (StandbyMode && stat_buf.st_size < expectedSize)
elevel = DEBUG1;
else
elevel = FATAL;
ereport(elevel,
(errmsg("archive file \"%s\" has wrong size: %lu instead of %lu",
xlogfname,
(unsigned long) stat_buf.st_size,
(unsigned long) expectedSize)));
return false;
}
else
{
ereport(LOG,
(errmsg("restored log file \"%s\" from archive",
xlogfname)));
strcpy(path, xlogpath);
return true;
}
}
else
{
/* stat failed */
if (errno != ENOENT)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m",
xlogpath)));
}
}
/*
* Remember, we rollforward UNTIL the restore fails so failure here is
* just part of the process... that makes it difficult to determine
* whether the restore failed because there isn't an archive to restore,
* or because the administrator has specified the restore program
* incorrectly. We have to assume the former.
*
* However, if the failure was due to any sort of signal, it's best to
* punt and abort recovery. (If we "return false" here, upper levels will
* assume that recovery is complete and start up the database!) It's
* essential to abort on child SIGINT and SIGQUIT, because per spec
* system() ignores SIGINT and SIGQUIT while waiting; if we see one of
* those it's a good bet we should have gotten it too.
*
* On SIGTERM, assume we have received a fast shutdown request, and exit
* cleanly. It's pure chance whether we receive the SIGTERM first, or the
* child process. If we receive it first, the signal handler will call
* proc_exit, otherwise we do it here. If we or the child process received
* SIGTERM for any other reason than a fast shutdown request, postmaster
* will perform an immediate shutdown when it sees us exiting
* unexpectedly.
*
* Per the Single Unix Spec, shells report exit status > 128 when a called
* command died on a signal. Also, 126 and 127 are used to report
* problems such as an unfindable command; treat those as fatal errors
* too.
*/
if (WIFSIGNALED(rc) && WTERMSIG(rc) == SIGTERM)
proc_exit(1);
signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
ereport(signaled ? FATAL : DEBUG2,
(errmsg("could not restore file \"%s\" from archive: return code %d",
xlogfname, rc)));
not_available:
/*
* if an archived file is not available, there might still be a version of
* this file in XLOGDIR, so return that as the filename to open.
*
* In many recovery scenarios we expect this to fail also, but if so that
* just means we've reached the end of WAL.
*/
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
return false;
}
| bool XLogArchiveCheckDone | ( | const char * | xlog | ) |
Definition at line 621 of file xlogarchive.c.
References StatusFilePath, XLogArchiveNotify(), and XLogArchivingActive.
Referenced by CleanupBackupHistory(), and RemoveOldXlogFiles().
{
char archiveStatusPath[MAXPGPATH];
struct stat stat_buf;
/* Always deletable if archiving is off */
if (!XLogArchivingActive())
return true;
/* First check for .done --- this means archiver is done with it */
StatusFilePath(archiveStatusPath, xlog, ".done");
if (stat(archiveStatusPath, &stat_buf) == 0)
return true;
/* check for .ready --- this means archiver is still busy with it */
StatusFilePath(archiveStatusPath, xlog, ".ready");
if (stat(archiveStatusPath, &stat_buf) == 0)
return false;
/* Race condition --- maybe archiver just finished, so recheck */
StatusFilePath(archiveStatusPath, xlog, ".done");
if (stat(archiveStatusPath, &stat_buf) == 0)
return true;
/* Retry creation of the .ready file */
XLogArchiveNotify(xlog);
return false;
}
| void XLogArchiveCleanup | ( | const char * | xlog | ) |
Definition at line 700 of file xlogarchive.c.
References StatusFilePath, and unlink().
Referenced by CleanupBackupHistory(), exitArchiveRecovery(), and RemoveOldXlogFiles().
{
char archiveStatusPath[MAXPGPATH];
/* Remove the .done file */
StatusFilePath(archiveStatusPath, xlog, ".done");
unlink(archiveStatusPath);
/* should we complain about failure? */
/* Remove the .ready file if present --- normally it shouldn't be */
StatusFilePath(archiveStatusPath, xlog, ".ready");
unlink(archiveStatusPath);
/* should we complain about failure? */
}
| void XLogArchiveForceDone | ( | const char * | xlog | ) |
Definition at line 561 of file xlogarchive.c.
References AllocateFile(), ereport, errcode_for_file_access(), errmsg(), FreeFile(), LOG, NULL, StatusFilePath, and WARNING.
Referenced by KeepFileRestoredFromArchive(), WalReceiverMain(), and XLogWalRcvWrite().
{
char archiveReady[MAXPGPATH];
char archiveDone[MAXPGPATH];
struct stat stat_buf;
FILE *fd;
/* Exit if already known done */
StatusFilePath(archiveDone, xlog, ".done");
if (stat(archiveDone, &stat_buf) == 0)
return;
/* If .ready exists, rename it to .done */
StatusFilePath(archiveReady, xlog, ".ready");
if (stat(archiveReady, &stat_buf) == 0)
{
if (rename(archiveReady, archiveDone) < 0)
ereport(WARNING,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
archiveReady, archiveDone)));
return;
}
/* insert an otherwise empty file called <XLOG>.done */
fd = AllocateFile(archiveDone, "w");
if (fd == NULL)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not create archive status file \"%s\": %m",
archiveDone)));
return;
}
if (FreeFile(fd))
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write archive status file \"%s\": %m",
archiveDone)));
return;
}
}
| bool XLogArchiveIsBusy | ( | const char * | xlog | ) |
Definition at line 661 of file xlogarchive.c.
References MAXPGPATH, snprintf(), StatusFilePath, and XLOGDIR.
Referenced by do_pg_stop_backup().
{
char archiveStatusPath[MAXPGPATH];
struct stat stat_buf;
/* First check for .done --- this means archiver is done with it */
StatusFilePath(archiveStatusPath, xlog, ".done");
if (stat(archiveStatusPath, &stat_buf) == 0)
return false;
/* check for .ready --- this means archiver is still busy with it */
StatusFilePath(archiveStatusPath, xlog, ".ready");
if (stat(archiveStatusPath, &stat_buf) == 0)
return true;
/* Race condition --- maybe archiver just finished, so recheck */
StatusFilePath(archiveStatusPath, xlog, ".done");
if (stat(archiveStatusPath, &stat_buf) == 0)
return false;
/*
* Check to see if the WAL file has been removed by checkpoint, which
* implies it has already been archived, and explains why we can't see a
* status file for it.
*/
snprintf(archiveStatusPath, MAXPGPATH, XLOGDIR "/%s", xlog);
if (stat(archiveStatusPath, &stat_buf) != 0 &&
errno == ENOENT)
return false;
return true;
}
| void XLogArchiveNotify | ( | const char * | xlog | ) |
Definition at line 511 of file xlogarchive.c.
References AllocateFile(), ereport, errcode_for_file_access(), errmsg(), FreeFile(), IsUnderPostmaster, LOG, NULL, PMSIGNAL_WAKEN_ARCHIVER, SendPostmasterSignal(), and StatusFilePath.
Referenced by exitArchiveRecovery(), writeTimeLineHistory(), XLogArchiveCheckDone(), and XLogArchiveNotifySeg().
{
char archiveStatusPath[MAXPGPATH];
FILE *fd;
/* insert an otherwise empty file called <XLOG>.ready */
StatusFilePath(archiveStatusPath, xlog, ".ready");
fd = AllocateFile(archiveStatusPath, "w");
if (fd == NULL)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not create archive status file \"%s\": %m",
archiveStatusPath)));
return;
}
if (FreeFile(fd))
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write archive status file \"%s\": %m",
archiveStatusPath)));
return;
}
/* Notify archiver that it's got something to do */
if (IsUnderPostmaster)
SendPostmasterSignal(PMSIGNAL_WAKEN_ARCHIVER);
}
| void XLogArchiveNotifySeg | ( | XLogSegNo | segno | ) |
Definition at line 545 of file xlogarchive.c.
References ThisTimeLineID, XLogArchiveNotify(), and XLogFileName.
Referenced by XLogWrite().
{
char xlog[MAXFNAMELEN];
XLogFileName(xlog, ThisTimeLineID, segno);
XLogArchiveNotify(xlog);
}
Definition at line 203 of file xlog.c.
Referenced by existsTimeLineHistory(), ReadRecord(), readRecoveryCommandFile(), readTimeLineHistory(), StartupXLOG(), writeTimeLineHistory(), and xlog_redo().
Definition at line 204 of file xlog.c.
Referenced by CheckRequiredParameterValues(), exitArchiveRecovery(), ReadRecord(), StartupXLOG(), and WaitForWALToBecomeAvailable().
| char* recoveryRestoreCommand |
Definition at line 210 of file xlog.c.
Referenced by readRecoveryCommandFile(), and RestoreArchivedFile().
Definition at line 31 of file rmgr.c.
Referenced by RecoveryRestartPoint(), rm_redo_error_callback(), StartupXLOG(), and XLogInsert().
Definition at line 226 of file xlog.c.
Referenced by ReadRecord(), RestoreArchivedFile(), StartupXLOG(), WaitForWALToBecomeAvailable(), and XLogPageRead().
1.7.1