|
|
|
|
@@ -926,9 +926,9 @@ begin:;
|
|
|
|
|
* affect the contents of the XLOG record, so we'll update our local copy
|
|
|
|
|
* but not force a recomputation.
|
|
|
|
|
*/
|
|
|
|
|
if (!XLByteEQ(RedoRecPtr, Insert->RedoRecPtr))
|
|
|
|
|
if (RedoRecPtr != Insert->RedoRecPtr)
|
|
|
|
|
{
|
|
|
|
|
Assert(XLByteLT(RedoRecPtr, Insert->RedoRecPtr));
|
|
|
|
|
Assert(RedoRecPtr < Insert->RedoRecPtr);
|
|
|
|
|
RedoRecPtr = Insert->RedoRecPtr;
|
|
|
|
|
|
|
|
|
|
if (doPageWrites)
|
|
|
|
|
@@ -938,7 +938,7 @@ begin:;
|
|
|
|
|
if (dtbuf[i] == InvalidBuffer)
|
|
|
|
|
continue;
|
|
|
|
|
if (dtbuf_bkp[i] == false &&
|
|
|
|
|
XLByteLE(dtbuf_lsn[i], RedoRecPtr))
|
|
|
|
|
dtbuf_lsn[i] <= RedoRecPtr)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Oops, this buffer now needs to be backed up, but we
|
|
|
|
|
@@ -1002,7 +1002,7 @@ begin:;
|
|
|
|
|
|
|
|
|
|
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
|
|
|
|
|
LogwrtResult = XLogCtl->LogwrtResult;
|
|
|
|
|
if (!XLByteLE(RecPtr, LogwrtResult.Flush))
|
|
|
|
|
if (LogwrtResult.Flush < RecPtr)
|
|
|
|
|
{
|
|
|
|
|
XLogwrtRqst FlushRqst;
|
|
|
|
|
|
|
|
|
|
@@ -1150,9 +1150,9 @@ begin:;
|
|
|
|
|
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
xlogctl->LogwrtResult = LogwrtResult;
|
|
|
|
|
if (XLByteLT(xlogctl->LogwrtRqst.Write, LogwrtResult.Write))
|
|
|
|
|
if (xlogctl->LogwrtRqst.Write < LogwrtResult.Write)
|
|
|
|
|
xlogctl->LogwrtRqst.Write = LogwrtResult.Write;
|
|
|
|
|
if (XLByteLT(xlogctl->LogwrtRqst.Flush, LogwrtResult.Flush))
|
|
|
|
|
if (xlogctl->LogwrtRqst.Flush < LogwrtResult.Flush)
|
|
|
|
|
xlogctl->LogwrtRqst.Flush = LogwrtResult.Flush;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
}
|
|
|
|
|
@@ -1188,7 +1188,7 @@ begin:;
|
|
|
|
|
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
/* advance global request to include new block(s) */
|
|
|
|
|
if (XLByteLT(xlogctl->LogwrtRqst.Write, WriteRqst))
|
|
|
|
|
if (xlogctl->LogwrtRqst.Write < WriteRqst)
|
|
|
|
|
xlogctl->LogwrtRqst.Write = WriteRqst;
|
|
|
|
|
/* update local result copy while I have the chance */
|
|
|
|
|
LogwrtResult = xlogctl->LogwrtResult;
|
|
|
|
|
@@ -1227,7 +1227,7 @@ XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
|
|
|
|
|
*lsn = PageGetLSN(page);
|
|
|
|
|
|
|
|
|
|
if (doPageWrites &&
|
|
|
|
|
XLByteLE(PageGetLSN(page), RedoRecPtr))
|
|
|
|
|
PageGetLSN(page) <= RedoRecPtr)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* The page needs to be backed up, so set up *bkpb
|
|
|
|
|
@@ -1300,7 +1300,7 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|
|
|
|
* written out.
|
|
|
|
|
*/
|
|
|
|
|
OldPageRqstPtr = XLogCtl->xlblocks[nextidx];
|
|
|
|
|
if (!XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
|
|
|
|
|
if (LogwrtResult.Write < OldPageRqstPtr)
|
|
|
|
|
{
|
|
|
|
|
/* nope, got work to do... */
|
|
|
|
|
XLogRecPtr FinishedPageRqstPtr;
|
|
|
|
|
@@ -1313,7 +1313,7 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|
|
|
|
volatile XLogCtlData *xlogctl = XLogCtl;
|
|
|
|
|
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
if (XLByteLT(xlogctl->LogwrtRqst.Write, FinishedPageRqstPtr))
|
|
|
|
|
if (xlogctl->LogwrtRqst.Write < FinishedPageRqstPtr)
|
|
|
|
|
xlogctl->LogwrtRqst.Write = FinishedPageRqstPtr;
|
|
|
|
|
LogwrtResult = xlogctl->LogwrtResult;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
@@ -1325,12 +1325,12 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|
|
|
|
* Now that we have an up-to-date LogwrtResult value, see if we still
|
|
|
|
|
* need to write it or if someone else already did.
|
|
|
|
|
*/
|
|
|
|
|
if (!XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
|
|
|
|
|
if (LogwrtResult.Write < OldPageRqstPtr)
|
|
|
|
|
{
|
|
|
|
|
/* Must acquire write lock */
|
|
|
|
|
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
|
|
|
|
|
LogwrtResult = XLogCtl->LogwrtResult;
|
|
|
|
|
if (XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
|
|
|
|
|
if (LogwrtResult.Write >= OldPageRqstPtr)
|
|
|
|
|
{
|
|
|
|
|
/* OK, someone wrote it already */
|
|
|
|
|
LWLockRelease(WALWriteLock);
|
|
|
|
|
@@ -1361,12 +1361,11 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|
|
|
|
{
|
|
|
|
|
/* force it to a segment start point */
|
|
|
|
|
if (NewPageBeginPtr % XLogSegSize != 0)
|
|
|
|
|
XLByteAdvance(NewPageBeginPtr,
|
|
|
|
|
XLogSegSize - NewPageBeginPtr % XLogSegSize);
|
|
|
|
|
NewPageBeginPtr += XLogSegSize - NewPageBeginPtr % XLogSegSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NewPageEndPtr = NewPageBeginPtr;
|
|
|
|
|
XLByteAdvance(NewPageEndPtr, XLOG_BLCKSZ);
|
|
|
|
|
NewPageEndPtr += XLOG_BLCKSZ;
|
|
|
|
|
XLogCtl->xlblocks[nextidx] = NewPageEndPtr;
|
|
|
|
|
NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
|
|
|
|
|
|
|
|
|
|
@@ -1503,14 +1502,14 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|
|
|
|
*/
|
|
|
|
|
curridx = Write->curridx;
|
|
|
|
|
|
|
|
|
|
while (XLByteLT(LogwrtResult.Write, WriteRqst.Write))
|
|
|
|
|
while (LogwrtResult.Write < WriteRqst.Write)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Make sure we're not ahead of the insert process. This could happen
|
|
|
|
|
* if we're passed a bogus WriteRqst.Write that is past the end of the
|
|
|
|
|
* last page that's been initialized by AdvanceXLInsertBuffer.
|
|
|
|
|
*/
|
|
|
|
|
if (!XLByteLT(LogwrtResult.Write, XLogCtl->xlblocks[curridx]))
|
|
|
|
|
if (LogwrtResult.Write >= XLogCtl->xlblocks[curridx])
|
|
|
|
|
elog(PANIC, "xlog write request %X/%X is past end of log %X/%X",
|
|
|
|
|
(uint32) (LogwrtResult.Write >> 32), (uint32) LogwrtResult.Write,
|
|
|
|
|
(uint32) (XLogCtl->xlblocks[curridx] >> 32),
|
|
|
|
|
@@ -1518,7 +1517,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|
|
|
|
|
|
|
|
|
/* Advance LogwrtResult.Write to end of current buffer page */
|
|
|
|
|
LogwrtResult.Write = XLogCtl->xlblocks[curridx];
|
|
|
|
|
ispartialpage = XLByteLT(WriteRqst.Write, LogwrtResult.Write);
|
|
|
|
|
ispartialpage = WriteRqst.Write < LogwrtResult.Write;
|
|
|
|
|
|
|
|
|
|
if (!XLByteInPrevSeg(LogwrtResult.Write, openLogSegNo))
|
|
|
|
|
{
|
|
|
|
|
@@ -1560,7 +1559,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|
|
|
|
* contiguous in memory), or if we are at the end of the logfile
|
|
|
|
|
* segment.
|
|
|
|
|
*/
|
|
|
|
|
last_iteration = !XLByteLT(LogwrtResult.Write, WriteRqst.Write);
|
|
|
|
|
last_iteration = WriteRqst.Write <= LogwrtResult.Write;
|
|
|
|
|
|
|
|
|
|
finishing_seg = !ispartialpage &&
|
|
|
|
|
(startoffset + npages * XLOG_BLCKSZ) >= XLogSegSize;
|
|
|
|
|
@@ -1671,8 +1670,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|
|
|
|
/*
|
|
|
|
|
* If asked to flush, do so
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(LogwrtResult.Flush, WriteRqst.Flush) &&
|
|
|
|
|
XLByteLT(LogwrtResult.Flush, LogwrtResult.Write))
|
|
|
|
|
if (LogwrtResult.Flush < WriteRqst.Flush &&
|
|
|
|
|
LogwrtResult.Flush < LogwrtResult.Write)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Could get here without iterating above loop, in which case we might
|
|
|
|
|
@@ -1714,9 +1714,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|
|
|
|
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
xlogctl->LogwrtResult = LogwrtResult;
|
|
|
|
|
if (XLByteLT(xlogctl->LogwrtRqst.Write, LogwrtResult.Write))
|
|
|
|
|
if (xlogctl->LogwrtRqst.Write < LogwrtResult.Write)
|
|
|
|
|
xlogctl->LogwrtRqst.Write = LogwrtResult.Write;
|
|
|
|
|
if (XLByteLT(xlogctl->LogwrtRqst.Flush, LogwrtResult.Flush))
|
|
|
|
|
if (xlogctl->LogwrtRqst.Flush < LogwrtResult.Flush)
|
|
|
|
|
xlogctl->LogwrtRqst.Flush = LogwrtResult.Flush;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
}
|
|
|
|
|
@@ -1739,7 +1739,7 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
LogwrtResult = xlogctl->LogwrtResult;
|
|
|
|
|
sleeping = xlogctl->WalWriterSleeping;
|
|
|
|
|
if (XLByteLT(xlogctl->asyncXactLSN, asyncXactLSN))
|
|
|
|
|
if (xlogctl->asyncXactLSN < asyncXactLSN)
|
|
|
|
|
xlogctl->asyncXactLSN = asyncXactLSN;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
|
|
|
|
|
@@ -1754,7 +1754,7 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
|
|
|
|
|
WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
|
|
|
|
|
|
|
|
|
|
/* if we have already flushed that far, we're done */
|
|
|
|
|
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
|
|
|
|
|
if (WriteRqstPtr <= LogwrtResult.Flush)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1780,7 +1780,7 @@ static void
|
|
|
|
|
UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|
|
|
|
{
|
|
|
|
|
/* Quick check using our local copy of the variable */
|
|
|
|
|
if (!updateMinRecoveryPoint || (!force && XLByteLE(lsn, minRecoveryPoint)))
|
|
|
|
|
if (!updateMinRecoveryPoint || (!force && lsn <= minRecoveryPoint))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
|
|
|
|
|
@@ -1796,7 +1796,7 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|
|
|
|
*/
|
|
|
|
|
if (minRecoveryPoint == 0)
|
|
|
|
|
updateMinRecoveryPoint = false;
|
|
|
|
|
else if (force || XLByteLT(minRecoveryPoint, lsn))
|
|
|
|
|
else if (force || minRecoveryPoint < lsn)
|
|
|
|
|
{
|
|
|
|
|
/* use volatile pointer to prevent code rearrangement */
|
|
|
|
|
volatile XLogCtlData *xlogctl = XLogCtl;
|
|
|
|
|
@@ -1821,7 +1821,7 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|
|
|
|
newMinRecoveryPointTLI = xlogctl->replayEndTLI;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
|
|
|
|
|
if (!force && XLByteLT(newMinRecoveryPoint, lsn))
|
|
|
|
|
if (!force && newMinRecoveryPoint < lsn)
|
|
|
|
|
elog(WARNING,
|
|
|
|
|
"xlog min recovery request %X/%X is past current point %X/%X",
|
|
|
|
|
(uint32) (lsn >> 32) , (uint32) lsn,
|
|
|
|
|
@@ -1829,7 +1829,7 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|
|
|
|
(uint32) newMinRecoveryPoint);
|
|
|
|
|
|
|
|
|
|
/* update control file */
|
|
|
|
|
if (XLByteLT(ControlFile->minRecoveryPoint, newMinRecoveryPoint))
|
|
|
|
|
if (ControlFile->minRecoveryPoint < newMinRecoveryPoint)
|
|
|
|
|
{
|
|
|
|
|
ControlFile->minRecoveryPoint = newMinRecoveryPoint;
|
|
|
|
|
ControlFile->minRecoveryPointTLI = newMinRecoveryPointTLI;
|
|
|
|
|
@@ -1873,7 +1873,7 @@ XLogFlush(XLogRecPtr record)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Quick exit if already known flushed */
|
|
|
|
|
if (XLByteLE(record, LogwrtResult.Flush))
|
|
|
|
|
if (record <= LogwrtResult.Flush)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
#ifdef WAL_DEBUG
|
|
|
|
|
@@ -1908,13 +1908,13 @@ XLogFlush(XLogRecPtr record)
|
|
|
|
|
|
|
|
|
|
/* read LogwrtResult and update local state */
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
if (XLByteLT(WriteRqstPtr, xlogctl->LogwrtRqst.Write))
|
|
|
|
|
if (WriteRqstPtr < xlogctl->LogwrtRqst.Write)
|
|
|
|
|
WriteRqstPtr = xlogctl->LogwrtRqst.Write;
|
|
|
|
|
LogwrtResult = xlogctl->LogwrtResult;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
|
|
|
|
|
/* done already? */
|
|
|
|
|
if (XLByteLE(record, LogwrtResult.Flush))
|
|
|
|
|
if (record <= LogwrtResult.Flush)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -1936,7 +1936,7 @@ XLogFlush(XLogRecPtr record)
|
|
|
|
|
|
|
|
|
|
/* Got the lock; recheck whether request is satisfied */
|
|
|
|
|
LogwrtResult = XLogCtl->LogwrtResult;
|
|
|
|
|
if (XLByteLE(record, LogwrtResult.Flush))
|
|
|
|
|
if (record <= LogwrtResult.Flush)
|
|
|
|
|
{
|
|
|
|
|
LWLockRelease(WALWriteLock);
|
|
|
|
|
break;
|
|
|
|
|
@@ -2010,7 +2010,7 @@ XLogFlush(XLogRecPtr record)
|
|
|
|
|
* calls from bufmgr.c are not within critical sections and so we will not
|
|
|
|
|
* force a restart for a bad LSN on a data page.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(LogwrtResult.Flush, record))
|
|
|
|
|
if (LogwrtResult.Flush < record)
|
|
|
|
|
elog(ERROR,
|
|
|
|
|
"xlog flush request %X/%X is not satisfied --- flushed only to %X/%X",
|
|
|
|
|
(uint32) (record >> 32), (uint32) record,
|
|
|
|
|
@@ -2060,7 +2060,7 @@ XLogBackgroundFlush(void)
|
|
|
|
|
WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
|
|
|
|
|
|
|
|
|
|
/* if we have already flushed that far, consider async commit records */
|
|
|
|
|
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
|
|
|
|
|
if (WriteRqstPtr <= LogwrtResult.Flush)
|
|
|
|
|
{
|
|
|
|
|
/* use volatile pointer to prevent code rearrangement */
|
|
|
|
|
volatile XLogCtlData *xlogctl = XLogCtl;
|
|
|
|
|
@@ -2076,7 +2076,7 @@ XLogBackgroundFlush(void)
|
|
|
|
|
* holding an open file handle to a logfile that's no longer in use,
|
|
|
|
|
* preventing the file from being deleted.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
|
|
|
|
|
if (WriteRqstPtr <= LogwrtResult.Flush)
|
|
|
|
|
{
|
|
|
|
|
if (openLogFile >= 0)
|
|
|
|
|
{
|
|
|
|
|
@@ -2101,7 +2101,7 @@ XLogBackgroundFlush(void)
|
|
|
|
|
/* now wait for the write lock */
|
|
|
|
|
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
|
|
|
|
|
LogwrtResult = XLogCtl->LogwrtResult;
|
|
|
|
|
if (!XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
|
|
|
|
|
if (WriteRqstPtr > LogwrtResult.Flush)
|
|
|
|
|
{
|
|
|
|
|
XLogwrtRqst WriteRqst;
|
|
|
|
|
|
|
|
|
|
@@ -2137,7 +2137,7 @@ XLogNeedsFlush(XLogRecPtr record)
|
|
|
|
|
if (RecoveryInProgress())
|
|
|
|
|
{
|
|
|
|
|
/* Quick exit if already known updated */
|
|
|
|
|
if (XLByteLE(record, minRecoveryPoint) || !updateMinRecoveryPoint)
|
|
|
|
|
if (record <= minRecoveryPoint || !updateMinRecoveryPoint)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -2160,14 +2160,14 @@ XLogNeedsFlush(XLogRecPtr record)
|
|
|
|
|
updateMinRecoveryPoint = false;
|
|
|
|
|
|
|
|
|
|
/* check again */
|
|
|
|
|
if (XLByteLE(record, minRecoveryPoint) || !updateMinRecoveryPoint)
|
|
|
|
|
if (record <= minRecoveryPoint || !updateMinRecoveryPoint)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Quick exit if already known flushed */
|
|
|
|
|
if (XLByteLE(record, LogwrtResult.Flush))
|
|
|
|
|
if (record <= LogwrtResult.Flush)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* read LogwrtResult and update local state */
|
|
|
|
|
@@ -2181,7 +2181,7 @@ XLogNeedsFlush(XLogRecPtr record)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check again */
|
|
|
|
|
if (XLByteLE(record, LogwrtResult.Flush))
|
|
|
|
|
if (record <= LogwrtResult.Flush)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
@@ -3489,7 +3489,7 @@ retry:
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
/* Calculate pointer to beginning of next page */
|
|
|
|
|
XLByteAdvance(pagelsn, XLOG_BLCKSZ);
|
|
|
|
|
pagelsn += XLOG_BLCKSZ;
|
|
|
|
|
/* Wait for the next page to become available */
|
|
|
|
|
if (!XLogPageRead(&pagelsn, emode, false, false))
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -3674,7 +3674,7 @@ ValidXLogPageHeader(XLogPageHeader hdr, int emode, bool segmentonly)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!XLByteEQ(hdr->xlp_pageaddr, recaddr))
|
|
|
|
|
if (hdr->xlp_pageaddr != recaddr)
|
|
|
|
|
{
|
|
|
|
|
ereport(emode_for_corrupt_record(emode, recaddr),
|
|
|
|
|
(errmsg("unexpected pageaddr %X/%X in log segment %s, offset %u",
|
|
|
|
|
@@ -3785,7 +3785,7 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|
|
|
|
* We can't exactly verify the prev-link, but surely it should be less
|
|
|
|
|
* than the record's own address.
|
|
|
|
|
*/
|
|
|
|
|
if (!XLByteLT(record->xl_prev, *RecPtr))
|
|
|
|
|
if (!(record->xl_prev < *RecPtr))
|
|
|
|
|
{
|
|
|
|
|
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
|
|
|
|
(errmsg("record with incorrect prev-link %X/%X at %X/%X",
|
|
|
|
|
@@ -3801,7 +3801,7 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|
|
|
|
* check guards against torn WAL pages where a stale but valid-looking
|
|
|
|
|
* WAL record starts on a sector boundary.
|
|
|
|
|
*/
|
|
|
|
|
if (!XLByteEQ(record->xl_prev, ReadRecPtr))
|
|
|
|
|
if (record->xl_prev != ReadRecPtr)
|
|
|
|
|
{
|
|
|
|
|
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
|
|
|
|
(errmsg("record with incorrect prev-link %X/%X at %X/%X",
|
|
|
|
|
@@ -3873,7 +3873,7 @@ rescanLatestTimeLine(void)
|
|
|
|
|
* next timeline was forked off from it *after* the current recovery
|
|
|
|
|
* location.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(currentTle->end, EndRecPtr))
|
|
|
|
|
if (currentTle->end < EndRecPtr)
|
|
|
|
|
{
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
|
|
|
|
|
@@ -5438,7 +5438,7 @@ StartupXLOG(void)
|
|
|
|
|
* backup_label around that references a WAL segment that's
|
|
|
|
|
* already been archived.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(checkPoint.redo, checkPointLoc))
|
|
|
|
|
if (checkPoint.redo < checkPointLoc)
|
|
|
|
|
{
|
|
|
|
|
if (!ReadRecord(&(checkPoint.redo), LOG, false))
|
|
|
|
|
ereport(FATAL,
|
|
|
|
|
@@ -5539,7 +5539,7 @@ StartupXLOG(void)
|
|
|
|
|
|
|
|
|
|
RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
|
|
|
|
|
|
|
|
|
|
if (XLByteLT(RecPtr, checkPoint.redo))
|
|
|
|
|
if (RecPtr < checkPoint.redo)
|
|
|
|
|
ereport(PANIC,
|
|
|
|
|
(errmsg("invalid redo in checkpoint record")));
|
|
|
|
|
|
|
|
|
|
@@ -5548,7 +5548,7 @@ StartupXLOG(void)
|
|
|
|
|
* have been a clean shutdown and we did not have a recovery.conf file,
|
|
|
|
|
* then assume no recovery needed.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(checkPoint.redo, RecPtr))
|
|
|
|
|
if (checkPoint.redo < RecPtr)
|
|
|
|
|
{
|
|
|
|
|
if (wasShutdown)
|
|
|
|
|
ereport(PANIC,
|
|
|
|
|
@@ -5593,7 +5593,7 @@ StartupXLOG(void)
|
|
|
|
|
if (InArchiveRecovery)
|
|
|
|
|
{
|
|
|
|
|
/* initialize minRecoveryPoint if not set yet */
|
|
|
|
|
if (XLByteLT(ControlFile->minRecoveryPoint, checkPoint.redo))
|
|
|
|
|
if (ControlFile->minRecoveryPoint < checkPoint.redo)
|
|
|
|
|
{
|
|
|
|
|
ControlFile->minRecoveryPoint = checkPoint.redo;
|
|
|
|
|
ControlFile->minRecoveryPointTLI = checkPoint.ThisTimeLineID;
|
|
|
|
|
@@ -5797,7 +5797,7 @@ StartupXLOG(void)
|
|
|
|
|
* Find the first record that logically follows the checkpoint --- it
|
|
|
|
|
* might physically precede it, though.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(checkPoint.redo, RecPtr))
|
|
|
|
|
if (checkPoint.redo < RecPtr)
|
|
|
|
|
{
|
|
|
|
|
/* back up to find the record */
|
|
|
|
|
record = ReadRecord(&(checkPoint.redo), PANIC, false);
|
|
|
|
|
@@ -6048,7 +6048,7 @@ StartupXLOG(void)
|
|
|
|
|
* advanced beyond the WAL we processed.
|
|
|
|
|
*/
|
|
|
|
|
if (InRecovery &&
|
|
|
|
|
(XLByteLT(EndOfLog, minRecoveryPoint) ||
|
|
|
|
|
(EndOfLog < minRecoveryPoint ||
|
|
|
|
|
!XLogRecPtrIsInvalid(ControlFile->backupStartPoint)))
|
|
|
|
|
{
|
|
|
|
|
if (reachedStopPoint)
|
|
|
|
|
@@ -6377,7 +6377,7 @@ CheckRecoveryConsistency(void)
|
|
|
|
|
* Have we reached the point where our base backup was completed?
|
|
|
|
|
*/
|
|
|
|
|
if (!XLogRecPtrIsInvalid(ControlFile->backupEndPoint) &&
|
|
|
|
|
XLByteLE(ControlFile->backupEndPoint, EndRecPtr))
|
|
|
|
|
ControlFile->backupEndPoint <= EndRecPtr)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* We have reached the end of base backup, as indicated by pg_control.
|
|
|
|
|
@@ -6390,7 +6390,7 @@ CheckRecoveryConsistency(void)
|
|
|
|
|
|
|
|
|
|
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
|
|
|
|
|
|
|
|
|
|
if (XLByteLT(ControlFile->minRecoveryPoint, EndRecPtr))
|
|
|
|
|
if (ControlFile->minRecoveryPoint < EndRecPtr)
|
|
|
|
|
ControlFile->minRecoveryPoint = EndRecPtr;
|
|
|
|
|
|
|
|
|
|
ControlFile->backupStartPoint = InvalidXLogRecPtr;
|
|
|
|
|
@@ -6409,7 +6409,7 @@ CheckRecoveryConsistency(void)
|
|
|
|
|
* consistent yet.
|
|
|
|
|
*/
|
|
|
|
|
if (!reachedConsistency && !ControlFile->backupEndRequired &&
|
|
|
|
|
XLByteLE(minRecoveryPoint, XLogCtl->lastReplayedEndRecPtr) &&
|
|
|
|
|
minRecoveryPoint <= XLogCtl->lastReplayedEndRecPtr &&
|
|
|
|
|
XLogRecPtrIsInvalid(ControlFile->backupStartPoint))
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
@@ -6717,7 +6717,7 @@ GetRedoRecPtr(void)
|
|
|
|
|
volatile XLogCtlData *xlogctl = XLogCtl;
|
|
|
|
|
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
Assert(XLByteLE(RedoRecPtr, xlogctl->Insert.RedoRecPtr));
|
|
|
|
|
Assert(RedoRecPtr <= xlogctl->Insert.RedoRecPtr);
|
|
|
|
|
RedoRecPtr = xlogctl->Insert.RedoRecPtr;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
|
|
|
|
|
@@ -7309,7 +7309,7 @@ CreateCheckPoint(int flags)
|
|
|
|
|
* We now have ProcLastRecPtr = start of actual checkpoint record, recptr
|
|
|
|
|
* = end of actual checkpoint record.
|
|
|
|
|
*/
|
|
|
|
|
if (shutdown && !XLByteEQ(checkPoint.redo, ProcLastRecPtr))
|
|
|
|
|
if (shutdown && checkPoint.redo != ProcLastRecPtr)
|
|
|
|
|
ereport(PANIC,
|
|
|
|
|
(errmsg("concurrent transaction log activity while database system is shutting down")));
|
|
|
|
|
|
|
|
|
|
@@ -7542,7 +7542,7 @@ CreateRestartPoint(int flags)
|
|
|
|
|
* side-effect.
|
|
|
|
|
*/
|
|
|
|
|
if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
|
|
|
|
|
XLByteLE(lastCheckPoint.redo, ControlFile->checkPointCopy.redo))
|
|
|
|
|
lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
|
|
|
|
|
{
|
|
|
|
|
ereport(DEBUG2,
|
|
|
|
|
(errmsg("skipping restartpoint, already performed at %X/%X",
|
|
|
|
|
@@ -7605,7 +7605,7 @@ CreateRestartPoint(int flags)
|
|
|
|
|
*/
|
|
|
|
|
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
|
|
|
|
|
if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY &&
|
|
|
|
|
XLByteLT(ControlFile->checkPointCopy.redo, lastCheckPoint.redo))
|
|
|
|
|
ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
|
|
|
|
|
{
|
|
|
|
|
ControlFile->prevCheckPoint = ControlFile->checkPoint;
|
|
|
|
|
ControlFile->checkPoint = lastCheckPointRecPtr;
|
|
|
|
|
@@ -7944,7 +7944,7 @@ checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI)
|
|
|
|
|
* new timeline.
|
|
|
|
|
*/
|
|
|
|
|
if (!XLogRecPtrIsInvalid(minRecoveryPoint) &&
|
|
|
|
|
XLByteLT(lsn, minRecoveryPoint) &&
|
|
|
|
|
lsn < minRecoveryPoint &&
|
|
|
|
|
newTLI > minRecoveryPointTLI)
|
|
|
|
|
ereport(PANIC,
|
|
|
|
|
(errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
|
|
|
|
|
@@ -8143,7 +8143,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
|
|
|
|
|
|
|
|
|
memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
|
|
|
|
|
|
|
|
|
|
if (XLByteEQ(ControlFile->backupStartPoint, startpoint))
|
|
|
|
|
if (ControlFile->backupStartPoint == startpoint)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* We have reached the end of base backup, the point where
|
|
|
|
|
@@ -8156,7 +8156,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
|
|
|
|
|
|
|
|
|
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
|
|
|
|
|
|
|
|
|
|
if (XLByteLT(ControlFile->minRecoveryPoint, lsn))
|
|
|
|
|
if (ControlFile->minRecoveryPoint < lsn)
|
|
|
|
|
{
|
|
|
|
|
ControlFile->minRecoveryPoint = lsn;
|
|
|
|
|
ControlFile->minRecoveryPointTLI = ThisTimeLineID;
|
|
|
|
|
@@ -8191,7 +8191,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
|
|
|
|
*/
|
|
|
|
|
minRecoveryPoint = ControlFile->minRecoveryPoint;
|
|
|
|
|
minRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
|
|
|
|
|
if (minRecoveryPoint != 0 && XLByteLT(minRecoveryPoint, lsn))
|
|
|
|
|
if (minRecoveryPoint != 0 && minRecoveryPoint < lsn)
|
|
|
|
|
{
|
|
|
|
|
ControlFile->minRecoveryPoint = lsn;
|
|
|
|
|
ControlFile->minRecoveryPointTLI = ThisTimeLineID;
|
|
|
|
|
@@ -8219,7 +8219,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
|
|
|
|
if (!fpw)
|
|
|
|
|
{
|
|
|
|
|
SpinLockAcquire(&xlogctl->info_lck);
|
|
|
|
|
if (XLByteLT(xlogctl->lastFpwDisableRecPtr, ReadRecPtr))
|
|
|
|
|
if (xlogctl->lastFpwDisableRecPtr < ReadRecPtr)
|
|
|
|
|
xlogctl->lastFpwDisableRecPtr = ReadRecPtr;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
}
|
|
|
|
|
@@ -8584,7 +8584,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile)
|
|
|
|
|
recptr = xlogctl->lastFpwDisableRecPtr;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
|
|
|
|
|
if (!checkpointfpw || XLByteLE(startpoint, recptr))
|
|
|
|
|
if (!checkpointfpw || startpoint <= recptr)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
|
errmsg("WAL generated with full_page_writes=off was replayed "
|
|
|
|
|
@@ -8616,7 +8616,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile)
|
|
|
|
|
* either because only few buffers have been dirtied yet.
|
|
|
|
|
*/
|
|
|
|
|
LWLockAcquire(WALInsertLock, LW_SHARED);
|
|
|
|
|
if (XLByteLT(XLogCtl->Insert.lastBackupStart, startpoint))
|
|
|
|
|
if (XLogCtl->Insert.lastBackupStart < startpoint)
|
|
|
|
|
{
|
|
|
|
|
XLogCtl->Insert.lastBackupStart = startpoint;
|
|
|
|
|
gotUniqueStartpoint = true;
|
|
|
|
|
@@ -8933,7 +8933,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive)
|
|
|
|
|
recptr = xlogctl->lastFpwDisableRecPtr;
|
|
|
|
|
SpinLockRelease(&xlogctl->info_lck);
|
|
|
|
|
|
|
|
|
|
if (XLByteLE(startpoint, recptr))
|
|
|
|
|
if (startpoint <= recptr)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
|
errmsg("WAL generated with full_page_writes=off was replayed "
|
|
|
|
|
@@ -9402,7 +9402,7 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
|
|
|
|
retry:
|
|
|
|
|
/* See if we need to retrieve more data */
|
|
|
|
|
if (readFile < 0 ||
|
|
|
|
|
(readSource == XLOG_FROM_STREAM && !XLByteLT(*RecPtr, receivedUpto)))
|
|
|
|
|
(readSource == XLOG_FROM_STREAM && receivedUpto <= *RecPtr))
|
|
|
|
|
{
|
|
|
|
|
if (StandbyMode)
|
|
|
|
|
{
|
|
|
|
|
@@ -9772,17 +9772,17 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
|
|
|
|
|
* When we are behind, XLogReceiptTime will not advance, so the
|
|
|
|
|
* grace time allotted to conflicting queries will decrease.
|
|
|
|
|
*/
|
|
|
|
|
if (XLByteLT(RecPtr, receivedUpto))
|
|
|
|
|
if (RecPtr < receivedUpto)
|
|
|
|
|
havedata = true;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
XLogRecPtr latestChunkStart;
|
|
|
|
|
|
|
|
|
|
receivedUpto = GetWalRcvWriteRecPtr(&latestChunkStart, &receiveTLI);
|
|
|
|
|
if (XLByteLT(RecPtr, receivedUpto) && receiveTLI == curFileTLI)
|
|
|
|
|
if (RecPtr < receivedUpto && receiveTLI == curFileTLI)
|
|
|
|
|
{
|
|
|
|
|
havedata = true;
|
|
|
|
|
if (!XLByteLT(RecPtr, latestChunkStart))
|
|
|
|
|
if (latestChunkStart <= RecPtr)
|
|
|
|
|
{
|
|
|
|
|
XLogReceiptTime = GetCurrentTimestamp();
|
|
|
|
|
SetCurrentChunkStartTime(XLogReceiptTime);
|
|
|
|
|
@@ -9884,7 +9884,7 @@ emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
|
|
|
|
|
|
|
|
|
|
if (readSource == XLOG_FROM_PG_XLOG && emode == LOG)
|
|
|
|
|
{
|
|
|
|
|
if (XLByteEQ(RecPtr, lastComplaint))
|
|
|
|
|
if (RecPtr == lastComplaint)
|
|
|
|
|
emode = DEBUG1;
|
|
|
|
|
else
|
|
|
|
|
lastComplaint = RecPtr;
|
|
|
|
|
|