XLogRecPtr StartPos;
XLogRecPtr EndPos;
bool prevDoPageWrites = doPageWrites;
+ TimeLineID insertTLI;
/* we assume that all of the record header is in the first chunk */
Assert(rdata->len >= SizeOfXLogRecord);
if (!XLogInsertAllowed())
elog(ERROR, "cannot make new WAL entries during recovery");
+ /*
+ * Given that we're not in recovery, ThisTimeLineID is set and can't
+ * change, so we can read it without a lock.
+ */
+ insertTLI = XLogCtl->ThisTimeLineID;
+
/*----------
*
* We have now done all the preparatory work we can without holding a
* inserted. Copy the record in the space reserved.
*/
CopyXLogRecordToWAL(rechdr->xl_tot_len, isLogSwitch, rdata,
- StartPos, EndPos, ThisTimeLineID);
+ StartPos, EndPos, insertTLI);
/*
* Unless record is flagged as not important, update LSN of last
{
XLogRecPtr WriteRqstPtr;
XLogwrtRqst WriteRqst;
+ TimeLineID insertTLI = XLogCtl->ThisTimeLineID;
/*
* During REDO, we are reading not writing WAL. Therefore, instead of
WriteRqst.Write = insertpos;
WriteRqst.Flush = insertpos;
- XLogWrite(WriteRqst, ThisTimeLineID, false);
+ XLogWrite(WriteRqst, insertTLI, false);
LWLockRelease(WALWriteLock);
/* done */
static TimestampTz lastflush;
TimestampTz now;
int flushbytes;
+ TimeLineID insertTLI;
/* XLOG doesn't need flushing during recovery */
if (RecoveryInProgress())
return false;
+ /*
+ * Since we're not in recovery, ThisTimeLineID is set and can't change,
+ * so we can read it without a lock.
+ */
+ insertTLI = XLogCtl->ThisTimeLineID;
+
/* read LogwrtResult and update local state */
SpinLockAcquire(&XLogCtl->info_lck);
LogwrtResult = XLogCtl->LogwrtResult;
if (WriteRqst.Write > LogwrtResult.Write ||
WriteRqst.Flush > LogwrtResult.Flush)
{
- XLogWrite(WriteRqst, ThisTimeLineID, flexible);
+ XLogWrite(WriteRqst, insertTLI, flexible);
}
LWLockRelease(WALWriteLock);
* Great, done. To take some work off the critical path, try to initialize
* as many of the no-longer-needed WAL buffers for future use as we can.
*/
- AdvanceXLInsertBuffer(InvalidXLogRecPtr, ThisTimeLineID, true);
+ AdvanceXLInsertBuffer(InvalidXLogRecPtr, insertTLI, true);
/*
* If we determined that we need to write data, but somebody else
/*
* An end-of-recovery checkpoint is created before anyone is allowed to
* write WAL. To allow us to write the checkpoint record, temporarily
- * enable XLogInsertAllowed. (This also ensures ThisTimeLineID is
- * initialized, which we need here and in AdvanceXLInsertBuffer.)
+ * enable XLogInsertAllowed.
*/
if (flags & CHECKPOINT_END_OF_RECOVERY)
oldXLogAllowed = LocalSetXLogInsertAllowed();
- checkPoint.ThisTimeLineID = ThisTimeLineID;
+ checkPoint.ThisTimeLineID = XLogCtl->ThisTimeLineID;
if (flags & CHECKPOINT_END_OF_RECOVERY)
checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
else
- checkPoint.PrevTimeLineID = ThisTimeLineID;
+ checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
checkPoint.fullPageWrites = Insert->fullPageWrites;
KeepLogSeg(recptr, &_logSegNo);
}
_logSegNo--;
- RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr, ThisTimeLineID);
+ RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
+ checkPoint.ThisTimeLineID);
/*
* Make more log segments if needed. (Do this after recycling old log
* segments, since that may supply some of the needed files.)
*/
if (!shutdown)
- PreallocXlogFiles(recptr, ThisTimeLineID);
+ PreallocXlogFiles(recptr, checkPoint.ThisTimeLineID);
/*
* Truncate pg_subtrans if possible. We can throw away all data before
xlrec.end_time = GetCurrentTimestamp();
WALInsertLockAcquireExclusive();
- xlrec.ThisTimeLineID = ThisTimeLineID;
+ xlrec.ThisTimeLineID = XLogCtl->ThisTimeLineID;
xlrec.PrevTimeLineID = XLogCtl->PrevTimeLineID;
WALInsertLockRelease();
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
ControlFile->time = (pg_time_t) time(NULL);
ControlFile->minRecoveryPoint = recptr;
- ControlFile->minRecoveryPointTLI = ThisTimeLineID;
+ ControlFile->minRecoveryPointTLI = xlrec.ThisTimeLineID;
UpdateControlFile();
LWLockRelease(ControlFileLock);
/*
* Try to recycle segments on a useful timeline. If we've been promoted
* since the beginning of this restartpoint, use the new timeline chosen
- * at end of recovery (RecoveryInProgress() sets ThisTimeLineID in that
- * case). If we're still in recovery, use the timeline we're currently
- * replaying.
+ * at end of recovery. If we're still in recovery, use the timeline we're
+ * currently replaying.
*
* There is no guarantee that the WAL segments will be useful on the
* current timeline; if recovery proceeds to a new timeline right after
* and will go wasted until recycled on the next restartpoint. We'll live
* with that.
*/
- if (RecoveryInProgress())
- ThisTimeLineID = replayTLI;
+ if (!RecoveryInProgress())
+ replayTLI = XLogCtl->ThisTimeLineID;
- RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, ThisTimeLineID);
+ RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, replayTLI);
/*
* Make more log segments if needed. (Do this after recycling old log
* segments, since that may supply some of the needed files.)
*/
- PreallocXlogFiles(endptr, ThisTimeLineID);
-
- /*
- * ThisTimeLineID is normally not set when we're still in recovery.
- * However, recycling/preallocating segments above needed ThisTimeLineID
- * to determine which timeline to install the segments on. Reset it now,
- * to restore the normal state of affairs for debugging purposes.
- */
- if (RecoveryInProgress())
- ThisTimeLineID = 0;
+ PreallocXlogFiles(endptr, replayTLI);
/*
* Truncate pg_subtrans if possible. We can throw away all data before
XLogBeginInsert();
XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
- stoptli = ThisTimeLineID;
+
+ /*
+ * Given that we're not in recovery, ThisTimeLineID is set and can't
+ * change, so we can read it without a lock.
+ */
+ stoptli = XLogCtl->ThisTimeLineID;
/*
* Force a switch to a new xlog segment file, so that the backup is