Replace XLogRecPtr struct with a 64-bit integer.
This simplifies code that needs to do arithmetic on XLogRecPtrs. To avoid changing on-disk format of data pages, the LSN on data pages is still stored in the old format. That should keep pg_upgrade happy. However, we have XLogRecPtrs embedded in the control file, and in the structs that are sent over the replication protocol, so this changes breaks compatibility of pg_basebackup and server. I didn't do anything about this in this patch, per discussion on -hackers, the right thing to do would to be to change the replication protocol to be architecture-independent, so that you could use a newer version of pg_receivexlog, for example, against an older server version.
This commit is contained in:
parent
061e7efb1b
commit
0ab9d1c4b3
|
@ -206,7 +206,8 @@ page_header(PG_FUNCTION_ARGS)
|
|||
/* Extract information from the page header */
|
||||
|
||||
lsn = PageGetLSN(page);
|
||||
snprintf(lsnchar, sizeof(lsnchar), "%X/%X", lsn.xlogid, lsn.xrecoff);
|
||||
snprintf(lsnchar, sizeof(lsnchar), "%X/%X",
|
||||
(uint32) (lsn >> 32), (uint32) lsn);
|
||||
|
||||
values[0] = CStringGetTextDatum(lsnchar);
|
||||
values[1] = UInt16GetDatum(PageGetTLI(page));
|
||||
|
|
|
@ -197,7 +197,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
|
|||
SplitedPageLayout *dist = NULL,
|
||||
*ptr;
|
||||
BlockNumber oldrlink = InvalidBlockNumber;
|
||||
GistNSN oldnsn = {0, 0};
|
||||
GistNSN oldnsn = 0;
|
||||
SplitedPageLayout rootpg;
|
||||
BlockNumber blkno = BufferGetBlockNumber(buffer);
|
||||
bool is_rootsplit;
|
||||
|
@ -488,7 +488,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
|
|||
|
||||
/* Start from the root */
|
||||
firststack.blkno = GIST_ROOT_BLKNO;
|
||||
firststack.lsn.xrecoff = 0;
|
||||
firststack.lsn = 0;
|
||||
firststack.parent = NULL;
|
||||
firststack.downlinkoffnum = InvalidOffsetNumber;
|
||||
state.stack = stack = &firststack;
|
||||
|
|
|
@ -706,13 +706,7 @@ gistoptions(PG_FUNCTION_ARGS)
|
|||
XLogRecPtr
|
||||
GetXLogRecPtrForTemp(void)
|
||||
{
|
||||
static XLogRecPtr counter = {0, 1};
|
||||
|
||||
counter.xrecoff++;
|
||||
if (counter.xrecoff == 0)
|
||||
{
|
||||
counter.xlogid++;
|
||||
counter.xrecoff++;
|
||||
}
|
||||
static XLogRecPtr counter = 1;
|
||||
counter++;
|
||||
return counter;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
#include "access/transam.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
/* Handy constant for an invalid xlog recptr */
|
||||
const XLogRecPtr InvalidXLogRecPtr = {0, 0};
|
||||
|
||||
/*
|
||||
* Single-item cache for results of TransactionLogFetch. It's worth having
|
||||
* such a cache because we frequently find ourselves repeatedly checking the
|
||||
|
|
|
@ -333,8 +333,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
|
|||
|
||||
gxact->prepared_at = prepared_at;
|
||||
/* initialize LSN to 0 (start of WAL) */
|
||||
gxact->prepare_lsn.xlogid = 0;
|
||||
gxact->prepare_lsn.xrecoff = 0;
|
||||
gxact->prepare_lsn = 0;
|
||||
gxact->owner = owner;
|
||||
gxact->locking_xid = xid;
|
||||
gxact->valid = false;
|
||||
|
|
|
@ -951,7 +951,7 @@ RecordTransactionCommit(void)
|
|||
if (XLogStandbyInfoActive())
|
||||
nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
|
||||
&RelcacheInitFileInval);
|
||||
wrote_xlog = (XactLastRecEnd.xrecoff != 0);
|
||||
wrote_xlog = (XactLastRecEnd != 0);
|
||||
|
||||
/*
|
||||
* If we haven't been assigned an XID yet, we neither can, nor do we want
|
||||
|
@ -1200,7 +1200,7 @@ RecordTransactionCommit(void)
|
|||
SyncRepWaitForLSN(XactLastRecEnd);
|
||||
|
||||
/* Reset XactLastRecEnd until the next transaction writes something */
|
||||
XactLastRecEnd.xrecoff = 0;
|
||||
XactLastRecEnd = 0;
|
||||
|
||||
cleanup:
|
||||
/* Clean up local data */
|
||||
|
@ -1402,7 +1402,7 @@ RecordTransactionAbort(bool isSubXact)
|
|||
{
|
||||
/* Reset XactLastRecEnd until the next transaction writes something */
|
||||
if (!isSubXact)
|
||||
XactLastRecEnd.xrecoff = 0;
|
||||
XactLastRecEnd = 0;
|
||||
return InvalidTransactionId;
|
||||
}
|
||||
|
||||
|
@ -1501,7 +1501,7 @@ RecordTransactionAbort(bool isSubXact)
|
|||
|
||||
/* Reset XactLastRecEnd until the next transaction writes something */
|
||||
if (!isSubXact)
|
||||
XactLastRecEnd.xrecoff = 0;
|
||||
XactLastRecEnd = 0;
|
||||
|
||||
/* And clean up local data */
|
||||
if (rels)
|
||||
|
@ -2170,7 +2170,7 @@ PrepareTransaction(void)
|
|||
*/
|
||||
|
||||
/* Reset XactLastRecEnd until the next transaction writes something */
|
||||
XactLastRecEnd.xrecoff = 0;
|
||||
XactLastRecEnd = 0;
|
||||
|
||||
/*
|
||||
* Let others know about no transaction in progress by me. This has to be
|
||||
|
|
|
@ -252,9 +252,9 @@ static TimeLineID curFileTLI;
|
|||
* or start a new one; so it can be used to tell if the current transaction has
|
||||
* created any XLOG records.
|
||||
*/
|
||||
static XLogRecPtr ProcLastRecPtr = {0, 0};
|
||||
static XLogRecPtr ProcLastRecPtr = InvalidXLogRecPtr;
|
||||
|
||||
XLogRecPtr XactLastRecEnd = {0, 0};
|
||||
XLogRecPtr XactLastRecEnd = InvalidXLogRecPtr;
|
||||
|
||||
/*
|
||||
* RedoRecPtr is this backend's local copy of the REDO record pointer
|
||||
|
@ -278,7 +278,7 @@ static XLogRecPtr RedoRecPtr;
|
|||
* backwards to the REDO location after reading the checkpoint record,
|
||||
* because the REDO record can precede the checkpoint record.
|
||||
*/
|
||||
static XLogRecPtr RedoStartLSN = {0, 0};
|
||||
static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr;
|
||||
|
||||
/*----------
|
||||
* Shared-memory data structures for XLOG control
|
||||
|
@ -493,13 +493,7 @@ static ControlFileData *ControlFile = NULL;
|
|||
|
||||
/* Construct XLogRecPtr value for current insertion point */
|
||||
#define INSERT_RECPTR(recptr,Insert,curridx) \
|
||||
do { \
|
||||
(recptr).xlogid = XLogCtl->xlblocks[curridx].xlogid; \
|
||||
(recptr).xrecoff = \
|
||||
XLogCtl->xlblocks[curridx].xrecoff - INSERT_FREESPACE(Insert); \
|
||||
if (XLogCtl->xlblocks[curridx].xrecoff == 0) \
|
||||
(recptr).xlogid = XLogCtl->xlblocks[curridx].xlogid - 1; \
|
||||
} while(0)
|
||||
(recptr) = XLogCtl->xlblocks[curridx] - INSERT_FREESPACE(Insert)
|
||||
|
||||
#define PrevBufIdx(idx) \
|
||||
(((idx) == 0) ? XLogCtl->XLogCacheBlck : ((idx) - 1))
|
||||
|
@ -511,7 +505,7 @@ static ControlFileData *ControlFile = NULL;
|
|||
* Private, possibly out-of-date copy of shared LogwrtResult.
|
||||
* See discussion above.
|
||||
*/
|
||||
static XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}};
|
||||
static XLogwrtResult LogwrtResult = {0, 0};
|
||||
|
||||
/*
|
||||
* Codes indicating where we got a WAL file from during recovery, or where
|
||||
|
@ -745,8 +739,7 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
|
|||
*/
|
||||
if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
|
||||
{
|
||||
RecPtr.xlogid = 0;
|
||||
RecPtr.xrecoff = SizeOfXLogLongPHD; /* start of 1st chkpt record */
|
||||
RecPtr = SizeOfXLogLongPHD; /* start of 1st chkpt record */
|
||||
return RecPtr;
|
||||
}
|
||||
|
||||
|
@ -1011,13 +1004,12 @@ begin:;
|
|||
* everything is written and flushed through the end of the prior segment,
|
||||
* and return the prior segment's end address.
|
||||
*/
|
||||
if (isLogSwitch &&
|
||||
(RecPtr.xrecoff % XLogSegSize) == SizeOfXLogLongPHD)
|
||||
if (isLogSwitch && (RecPtr % XLogSegSize) == SizeOfXLogLongPHD)
|
||||
{
|
||||
/* We can release insert lock immediately */
|
||||
LWLockRelease(WALInsertLock);
|
||||
|
||||
RecPtr.xrecoff -= SizeOfXLogLongPHD;
|
||||
RecPtr -= SizeOfXLogLongPHD;
|
||||
|
||||
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
|
||||
LogwrtResult = XLogCtl->LogwrtResult;
|
||||
|
@ -1051,7 +1043,7 @@ begin:;
|
|||
|
||||
initStringInfo(&buf);
|
||||
appendStringInfo(&buf, "INSERT @ %X/%X: ",
|
||||
RecPtr.xlogid, RecPtr.xrecoff);
|
||||
(uint32) (RecPtr >> 32), (uint32) RecPtr);
|
||||
xlog_outrec(&buf, rechdr);
|
||||
if (rdata->data != NULL)
|
||||
{
|
||||
|
@ -1152,12 +1144,7 @@ begin:;
|
|||
|
||||
/* Compute end address of old segment */
|
||||
OldSegEnd = XLogCtl->xlblocks[curridx];
|
||||
if (OldSegEnd.xrecoff == 0)
|
||||
{
|
||||
/* crossing a logid boundary */
|
||||
OldSegEnd.xlogid -= 1;
|
||||
}
|
||||
OldSegEnd.xrecoff -= XLOG_BLCKSZ;
|
||||
OldSegEnd -= XLOG_BLCKSZ;
|
||||
|
||||
/* Make it look like we've written and synced all of old segment */
|
||||
LogwrtResult.Write = OldSegEnd;
|
||||
|
@ -1523,8 +1510,7 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|||
*/
|
||||
TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
|
||||
WriteRqst.Write = OldPageRqstPtr;
|
||||
WriteRqst.Flush.xlogid = 0;
|
||||
WriteRqst.Flush.xrecoff = 0;
|
||||
WriteRqst.Flush = 0;
|
||||
XLogWrite(WriteRqst, false, false);
|
||||
LWLockRelease(WALWriteLock);
|
||||
TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
|
||||
|
@ -1541,9 +1527,9 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|||
if (new_segment)
|
||||
{
|
||||
/* force it to a segment start point */
|
||||
if (NewPageBeginPtr.xrecoff % XLogSegSize != 0)
|
||||
if (NewPageBeginPtr % XLogSegSize != 0)
|
||||
XLByteAdvance(NewPageBeginPtr,
|
||||
XLogSegSize - NewPageBeginPtr.xrecoff % XLogSegSize);
|
||||
XLogSegSize - NewPageBeginPtr % XLogSegSize);
|
||||
}
|
||||
|
||||
NewPageEndPtr = NewPageBeginPtr;
|
||||
|
@ -1589,7 +1575,7 @@ AdvanceXLInsertBuffer(bool new_segment)
|
|||
/*
|
||||
* If first page of an XLOG segment file, make it a long header.
|
||||
*/
|
||||
if ((NewPage->xlp_pageaddr.xrecoff % XLogSegSize) == 0)
|
||||
if ((NewPage->xlp_pageaddr % XLogSegSize) == 0)
|
||||
{
|
||||
XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
|
||||
|
||||
|
@ -1693,9 +1679,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|||
*/
|
||||
if (!XLByteLT(LogwrtResult.Write, XLogCtl->xlblocks[curridx]))
|
||||
elog(PANIC, "xlog write request %X/%X is past end of log %X/%X",
|
||||
LogwrtResult.Write.xlogid, LogwrtResult.Write.xrecoff,
|
||||
XLogCtl->xlblocks[curridx].xlogid,
|
||||
XLogCtl->xlblocks[curridx].xrecoff);
|
||||
(uint32) (LogwrtResult.Write >> 32), (uint32) LogwrtResult.Write,
|
||||
(uint32) (XLogCtl->xlblocks[curridx] >> 32),
|
||||
(uint32) XLogCtl->xlblocks[curridx]);
|
||||
|
||||
/* Advance LogwrtResult.Write to end of current buffer page */
|
||||
LogwrtResult.Write = XLogCtl->xlblocks[curridx];
|
||||
|
@ -1731,7 +1717,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
|||
{
|
||||
/* first of group */
|
||||
startidx = curridx;
|
||||
startoffset = (LogwrtResult.Write.xrecoff - XLOG_BLCKSZ) % XLogSegSize;
|
||||
startoffset = (LogwrtResult.Write - XLOG_BLCKSZ) % XLogSegSize;
|
||||
}
|
||||
npages++;
|
||||
|
||||
|
@ -1923,7 +1909,7 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
|
|||
if (!sleeping)
|
||||
{
|
||||
/* back off to last completed page boundary */
|
||||
WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
|
||||
WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
|
||||
|
||||
/* if we have already flushed that far, we're done */
|
||||
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
|
||||
|
@ -1965,7 +1951,7 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|||
* i.e., we're doing crash recovery. We never modify the control file's
|
||||
* value in that case, so we can short-circuit future checks here too.
|
||||
*/
|
||||
if (minRecoveryPoint.xlogid == 0 && minRecoveryPoint.xrecoff == 0)
|
||||
if (minRecoveryPoint == 0)
|
||||
updateMinRecoveryPoint = false;
|
||||
else if (force || XLByteLT(minRecoveryPoint, lsn))
|
||||
{
|
||||
|
@ -1993,8 +1979,9 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|||
if (!force && XLByteLT(newMinRecoveryPoint, lsn))
|
||||
elog(WARNING,
|
||||
"xlog min recovery request %X/%X is past current point %X/%X",
|
||||
lsn.xlogid, lsn.xrecoff,
|
||||
newMinRecoveryPoint.xlogid, newMinRecoveryPoint.xrecoff);
|
||||
(uint32) (lsn >> 32) , (uint32) lsn,
|
||||
(uint32) (newMinRecoveryPoint >> 32),
|
||||
(uint32) newMinRecoveryPoint);
|
||||
|
||||
/* update control file */
|
||||
if (XLByteLT(ControlFile->minRecoveryPoint, newMinRecoveryPoint))
|
||||
|
@ -2005,7 +1992,8 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
|||
|
||||
ereport(DEBUG2,
|
||||
(errmsg("updated min recovery point to %X/%X",
|
||||
minRecoveryPoint.xlogid, minRecoveryPoint.xrecoff)));
|
||||
(uint32) (minRecoveryPoint >> 32),
|
||||
(uint32) minRecoveryPoint)));
|
||||
}
|
||||
}
|
||||
LWLockRelease(ControlFileLock);
|
||||
|
@ -2043,9 +2031,9 @@ XLogFlush(XLogRecPtr record)
|
|||
#ifdef WAL_DEBUG
|
||||
if (XLOG_DEBUG)
|
||||
elog(LOG, "xlog flush request %X/%X; write %X/%X; flush %X/%X",
|
||||
record.xlogid, record.xrecoff,
|
||||
LogwrtResult.Write.xlogid, LogwrtResult.Write.xrecoff,
|
||||
LogwrtResult.Flush.xlogid, LogwrtResult.Flush.xrecoff);
|
||||
(uint32) (record >> 32), (uint32) record,
|
||||
(uint32) (LogwrtResult.Write >> 32), (uint32) LogwrtResult.Write,
|
||||
(uint32) (LogwrtResult.Flush >> 32), (uint32) LogwrtResult.Flush);
|
||||
#endif
|
||||
|
||||
START_CRIT_SECTION();
|
||||
|
@ -2112,9 +2100,7 @@ XLogFlush(XLogRecPtr record)
|
|||
else
|
||||
{
|
||||
WriteRqstPtr = XLogCtl->xlblocks[Insert->curridx];
|
||||
if (WriteRqstPtr.xrecoff == 0)
|
||||
WriteRqstPtr.xlogid--;
|
||||
WriteRqstPtr.xrecoff -= freespace;
|
||||
WriteRqstPtr -= freespace;
|
||||
}
|
||||
LWLockRelease(WALInsertLock);
|
||||
WriteRqst.Write = WriteRqstPtr;
|
||||
|
@ -2158,8 +2144,8 @@ XLogFlush(XLogRecPtr record)
|
|||
if (XLByteLT(LogwrtResult.Flush, record))
|
||||
elog(ERROR,
|
||||
"xlog flush request %X/%X is not satisfied --- flushed only to %X/%X",
|
||||
record.xlogid, record.xrecoff,
|
||||
LogwrtResult.Flush.xlogid, LogwrtResult.Flush.xrecoff);
|
||||
(uint32) (record >> 32), (uint32) record,
|
||||
(uint32) (LogwrtResult.Flush >> 32), (uint32) LogwrtResult.Flush);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2202,7 +2188,7 @@ XLogBackgroundFlush(void)
|
|||
}
|
||||
|
||||
/* back off to last completed page boundary */
|
||||
WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
|
||||
WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
|
||||
|
||||
/* if we have already flushed that far, consider async commit records */
|
||||
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
|
||||
|
@ -2236,9 +2222,9 @@ XLogBackgroundFlush(void)
|
|||
#ifdef WAL_DEBUG
|
||||
if (XLOG_DEBUG)
|
||||
elog(LOG, "xlog bg flush request %X/%X; write %X/%X; flush %X/%X",
|
||||
WriteRqstPtr.xlogid, WriteRqstPtr.xrecoff,
|
||||
LogwrtResult.Write.xlogid, LogwrtResult.Write.xrecoff,
|
||||
LogwrtResult.Flush.xlogid, LogwrtResult.Flush.xrecoff);
|
||||
(uint32) (WriteRqstPtr >> 32), (uint32) WriteRqstPtr,
|
||||
(uint32) (LogwrtResult.Write >> 32), (uint32) LogwrtResult.Write,
|
||||
(uint32) (LogwrtResult.Flush >> 32), (uint32) LogwrtResult.Flush);
|
||||
#endif
|
||||
|
||||
START_CRIT_SECTION();
|
||||
|
@ -2305,7 +2291,7 @@ XLogNeedsFlush(XLogRecPtr record)
|
|||
* file's value in that case, so we can short-circuit future checks
|
||||
* here too.
|
||||
*/
|
||||
if (minRecoveryPoint.xlogid == 0 && minRecoveryPoint.xrecoff == 0)
|
||||
if (minRecoveryPoint == 0)
|
||||
updateMinRecoveryPoint = false;
|
||||
|
||||
/* check again */
|
||||
|
@ -3319,8 +3305,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
|
|||
bool use_existent;
|
||||
|
||||
XLByteToPrevSeg(endptr, _logSegNo);
|
||||
if ((endptr.xrecoff - 1) % XLogSegSize >=
|
||||
(uint32) (0.75 * XLogSegSize))
|
||||
if ((endptr - 1) % XLogSegSize >= (uint32) (0.75 * XLogSegSize))
|
||||
{
|
||||
_logSegNo++;
|
||||
use_existent = true;
|
||||
|
@ -3704,7 +3689,7 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, recptr),
|
||||
(errmsg("incorrect hole size in record at %X/%X",
|
||||
recptr.xlogid, recptr.xrecoff)));
|
||||
(uint32) (recptr >> 32), (uint32) recptr)));
|
||||
return false;
|
||||
}
|
||||
blen = sizeof(BkpBlock) + BLCKSZ - bkpb.hole_length;
|
||||
|
@ -3717,7 +3702,7 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, recptr),
|
||||
(errmsg("incorrect total length in record at %X/%X",
|
||||
recptr.xlogid, recptr.xrecoff)));
|
||||
(uint32) (recptr >> 32), (uint32) recptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3729,7 +3714,7 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, recptr),
|
||||
(errmsg("incorrect resource manager data checksum in record at %X/%X",
|
||||
recptr.xlogid, recptr.xrecoff)));
|
||||
(uint32) (recptr >> 32), (uint32) recptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3790,10 +3775,10 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
|
|||
* In this case, the passed-in record pointer should already be
|
||||
* pointing to a valid record starting position.
|
||||
*/
|
||||
if (!XRecOffIsValid(RecPtr->xrecoff))
|
||||
if (!XRecOffIsValid(*RecPtr))
|
||||
ereport(PANIC,
|
||||
(errmsg("invalid record offset at %X/%X",
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) (*RecPtr >> 32), (uint32) *RecPtr)));
|
||||
|
||||
/*
|
||||
* Since we are going to a random position in WAL, forget any prior
|
||||
|
@ -3814,7 +3799,7 @@ retry:
|
|||
return NULL;
|
||||
|
||||
pageHeaderSize = XLogPageHeaderSize((XLogPageHeader) readBuf);
|
||||
targetRecOff = RecPtr->xrecoff % XLOG_BLCKSZ;
|
||||
targetRecOff = (*RecPtr) % XLOG_BLCKSZ;
|
||||
if (targetRecOff == 0)
|
||||
{
|
||||
/*
|
||||
|
@ -3824,14 +3809,14 @@ retry:
|
|||
* XRecOffIsValid rejected the zero-page-offset case otherwise.
|
||||
*/
|
||||
Assert(RecPtr == &tmpRecPtr);
|
||||
RecPtr->xrecoff += pageHeaderSize;
|
||||
(*RecPtr) += pageHeaderSize;
|
||||
targetRecOff = pageHeaderSize;
|
||||
}
|
||||
else if (targetRecOff < pageHeaderSize)
|
||||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("invalid record offset at %X/%X",
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
goto next_record_is_invalid;
|
||||
}
|
||||
if ((((XLogPageHeader) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD) &&
|
||||
|
@ -3839,7 +3824,7 @@ retry:
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("contrecord is requested by %X/%X",
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
goto next_record_is_invalid;
|
||||
}
|
||||
|
||||
|
@ -3849,7 +3834,7 @@ retry:
|
|||
* struct, so it must be on this page, but we cannot safely access any
|
||||
* other fields yet.
|
||||
*/
|
||||
record = (XLogRecord *) (readBuf + RecPtr->xrecoff % XLOG_BLCKSZ);
|
||||
record = (XLogRecord *) (readBuf + (*RecPtr) % XLOG_BLCKSZ);
|
||||
total_len = record->xl_tot_len;
|
||||
|
||||
/*
|
||||
|
@ -3874,7 +3859,7 @@ retry:
|
|||
/* We treat this as a "bogus data" condition */
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("record length %u at %X/%X too long",
|
||||
total_len, RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
total_len, (uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
goto next_record_is_invalid;
|
||||
}
|
||||
readRecordBufSize = newSize;
|
||||
|
@ -3893,7 +3878,7 @@ retry:
|
|||
else
|
||||
gotheader = false;
|
||||
|
||||
len = XLOG_BLCKSZ - RecPtr->xrecoff % XLOG_BLCKSZ;
|
||||
len = XLOG_BLCKSZ - (*RecPtr) % XLOG_BLCKSZ;
|
||||
if (total_len > len)
|
||||
{
|
||||
/* Need to reassemble record */
|
||||
|
@ -3904,11 +3889,10 @@ retry:
|
|||
uint32 gotlen;
|
||||
|
||||
/* Initialize pagelsn to the beginning of the page this record is on */
|
||||
pagelsn = *RecPtr;
|
||||
pagelsn.xrecoff = (pagelsn.xrecoff / XLOG_BLCKSZ) * XLOG_BLCKSZ;
|
||||
pagelsn = ((*RecPtr) / XLOG_BLCKSZ) * XLOG_BLCKSZ;
|
||||
|
||||
/* Copy the first fragment of the record from the first page. */
|
||||
memcpy(readRecordBuf, readBuf + RecPtr->xrecoff % XLOG_BLCKSZ, len);
|
||||
memcpy(readRecordBuf, readBuf + (*RecPtr) % XLOG_BLCKSZ, len);
|
||||
buffer = readRecordBuf + len;
|
||||
gotlen = len;
|
||||
|
||||
|
@ -3980,8 +3964,7 @@ retry:
|
|||
/* Record does not cross a page boundary */
|
||||
if (!RecordIsValid(record, *RecPtr, emode))
|
||||
goto next_record_is_invalid;
|
||||
EndRecPtr.xlogid = RecPtr->xlogid;
|
||||
EndRecPtr.xrecoff = RecPtr->xrecoff + MAXALIGN(total_len);
|
||||
EndRecPtr = *RecPtr + MAXALIGN(total_len);
|
||||
|
||||
ReadRecPtr = *RecPtr;
|
||||
memcpy(readRecordBuf, record, total_len);
|
||||
|
@ -3993,8 +3976,8 @@ retry:
|
|||
if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_SWITCH)
|
||||
{
|
||||
/* Pretend it extends to end of segment */
|
||||
EndRecPtr.xrecoff += XLogSegSize - 1;
|
||||
EndRecPtr.xrecoff -= EndRecPtr.xrecoff % XLogSegSize;
|
||||
EndRecPtr += XLogSegSize - 1;
|
||||
EndRecPtr -= EndRecPtr % XLogSegSize;
|
||||
|
||||
/*
|
||||
* Pretend that readBuf contains the last page of the segment. This is
|
||||
|
@ -4105,7 +4088,7 @@ ValidXLogPageHeader(XLogPageHeader hdr, int emode)
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, recaddr),
|
||||
(errmsg("unexpected pageaddr %X/%X in log segment %s, offset %u",
|
||||
hdr->xlp_pageaddr.xlogid, hdr->xlp_pageaddr.xrecoff,
|
||||
(uint32) (hdr->xlp_pageaddr >> 32), (uint32) hdr->xlp_pageaddr,
|
||||
XLogFileNameP(curFileTLI, readSegNo),
|
||||
readOff)));
|
||||
return false;
|
||||
|
@ -4166,7 +4149,7 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("invalid xlog switch record at %X/%X",
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4174,7 +4157,7 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("record with zero length at %X/%X",
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
return false;
|
||||
}
|
||||
if (record->xl_tot_len < SizeOfXLogRecord + record->xl_len ||
|
||||
|
@ -4183,14 +4166,14 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("invalid record length at %X/%X",
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
return false;
|
||||
}
|
||||
if (record->xl_rmid > RM_MAX_ID)
|
||||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("invalid resource manager ID %u at %X/%X",
|
||||
record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
record->xl_rmid, (uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
return false;
|
||||
}
|
||||
if (randAccess)
|
||||
|
@ -4203,8 +4186,8 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("record with incorrect prev-link %X/%X at %X/%X",
|
||||
record->xl_prev.xlogid, record->xl_prev.xrecoff,
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) (record->xl_prev >> 32), (uint32) record->xl_prev,
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4219,8 +4202,8 @@ ValidXLogRecordHeader(XLogRecPtr *RecPtr, XLogRecord *record, int emode,
|
|||
{
|
||||
ereport(emode_for_corrupt_record(emode, *RecPtr),
|
||||
(errmsg("record with incorrect prev-link %X/%X at %X/%X",
|
||||
record->xl_prev.xlogid, record->xl_prev.xrecoff,
|
||||
RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
(uint32) (record->xl_prev >> 32), (uint32) record->xl_prev,
|
||||
(uint32) ((*RecPtr) >> 32), (uint32) *RecPtr)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -5193,8 +5176,7 @@ BootStrapXLOG(void)
|
|||
* segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
|
||||
* used, so that we can use 0/0 to mean "before any valid WAL segment".
|
||||
*/
|
||||
checkPoint.redo.xlogid = 0;
|
||||
checkPoint.redo.xrecoff = XLogSegSize + SizeOfXLogLongPHD;
|
||||
checkPoint.redo = XLogSegSize + SizeOfXLogLongPHD;
|
||||
checkPoint.ThisTimeLineID = ThisTimeLineID;
|
||||
checkPoint.fullPageWrites = fullPageWrites;
|
||||
checkPoint.nextXidEpoch = 0;
|
||||
|
@ -5217,8 +5199,7 @@ BootStrapXLOG(void)
|
|||
page->xlp_magic = XLOG_PAGE_MAGIC;
|
||||
page->xlp_info = XLP_LONG_HEADER;
|
||||
page->xlp_tli = ThisTimeLineID;
|
||||
page->xlp_pageaddr.xlogid = 0;
|
||||
page->xlp_pageaddr.xrecoff = XLogSegSize;
|
||||
page->xlp_pageaddr = XLogSegSize;
|
||||
longpage = (XLogLongPageHeader) page;
|
||||
longpage->xlp_sysid = sysidentifier;
|
||||
longpage->xlp_seg_size = XLogSegSize;
|
||||
|
@ -5226,8 +5207,7 @@ BootStrapXLOG(void)
|
|||
|
||||
/* Insert the initial checkpoint record */
|
||||
record = (XLogRecord *) ((char *) page + SizeOfXLogLongPHD);
|
||||
record->xl_prev.xlogid = 0;
|
||||
record->xl_prev.xrecoff = 0;
|
||||
record->xl_prev = 0;
|
||||
record->xl_xid = InvalidTransactionId;
|
||||
record->xl_tot_len = SizeOfXLogRecord + sizeof(checkPoint);
|
||||
record->xl_len = sizeof(checkPoint);
|
||||
|
@ -6021,7 +6001,7 @@ StartupXLOG(void)
|
|||
|
||||
if (ControlFile->state < DB_SHUTDOWNED ||
|
||||
ControlFile->state > DB_IN_PRODUCTION ||
|
||||
!XRecOffIsValid(ControlFile->checkPoint.xrecoff))
|
||||
!XRecOffIsValid(ControlFile->checkPoint))
|
||||
ereport(FATAL,
|
||||
(errmsg("control file contains invalid data")));
|
||||
|
||||
|
@ -6157,7 +6137,7 @@ StartupXLOG(void)
|
|||
wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN);
|
||||
ereport(DEBUG1,
|
||||
(errmsg("checkpoint record is at %X/%X",
|
||||
checkPointLoc.xlogid, checkPointLoc.xrecoff)));
|
||||
(uint32) (checkPointLoc >> 32), (uint32) checkPointLoc)));
|
||||
InRecovery = true; /* force recovery even if SHUTDOWNED */
|
||||
|
||||
/*
|
||||
|
@ -6197,7 +6177,7 @@ StartupXLOG(void)
|
|||
{
|
||||
ereport(DEBUG1,
|
||||
(errmsg("checkpoint record is at %X/%X",
|
||||
checkPointLoc.xlogid, checkPointLoc.xrecoff)));
|
||||
(uint32) (checkPointLoc >> 32), (uint32) checkPointLoc)));
|
||||
}
|
||||
else if (StandbyMode)
|
||||
{
|
||||
|
@ -6216,7 +6196,7 @@ StartupXLOG(void)
|
|||
{
|
||||
ereport(LOG,
|
||||
(errmsg("using previous checkpoint record at %X/%X",
|
||||
checkPointLoc.xlogid, checkPointLoc.xrecoff)));
|
||||
(uint32) (checkPointLoc >> 32), (uint32) checkPointLoc)));
|
||||
InRecovery = true; /* force recovery even if SHUTDOWNED */
|
||||
}
|
||||
else
|
||||
|
@ -6231,7 +6211,7 @@ StartupXLOG(void)
|
|||
|
||||
ereport(DEBUG1,
|
||||
(errmsg("redo record is at %X/%X; shutdown %s",
|
||||
checkPoint.redo.xlogid, checkPoint.redo.xrecoff,
|
||||
(uint32) (checkPoint.redo >> 32), (uint32) checkPoint.redo,
|
||||
wasShutdown ? "TRUE" : "FALSE")));
|
||||
ereport(DEBUG1,
|
||||
(errmsg("next transaction ID: %u/%u; next OID: %u",
|
||||
|
@ -6542,7 +6522,7 @@ StartupXLOG(void)
|
|||
|
||||
ereport(LOG,
|
||||
(errmsg("redo starts at %X/%X",
|
||||
ReadRecPtr.xlogid, ReadRecPtr.xrecoff)));
|
||||
(uint32) (ReadRecPtr >> 32), (uint32) ReadRecPtr)));
|
||||
|
||||
/*
|
||||
* main redo apply loop
|
||||
|
@ -6558,8 +6538,8 @@ StartupXLOG(void)
|
|||
|
||||
initStringInfo(&buf);
|
||||
appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
|
||||
ReadRecPtr.xlogid, ReadRecPtr.xrecoff,
|
||||
EndRecPtr.xlogid, EndRecPtr.xrecoff);
|
||||
(uint32) (ReadRecPtr >> 32), (uint32) ReadRecPtr,
|
||||
(uint32) (EndRecPtr >> 32), (uint32) EndRecPtr);
|
||||
xlog_outrec(&buf, record);
|
||||
appendStringInfo(&buf, " - ");
|
||||
RmgrTable[record->xl_rmid].rm_desc(&buf,
|
||||
|
@ -6687,7 +6667,7 @@ StartupXLOG(void)
|
|||
|
||||
ereport(LOG,
|
||||
(errmsg("redo done at %X/%X",
|
||||
ReadRecPtr.xlogid, ReadRecPtr.xrecoff)));
|
||||
(uint32) (ReadRecPtr >> 32), (uint32) ReadRecPtr)));
|
||||
xtime = GetLatestXTime();
|
||||
if (xtime)
|
||||
ereport(LOG,
|
||||
|
@ -6820,19 +6800,17 @@ StartupXLOG(void)
|
|||
openLogOff = 0;
|
||||
Insert = &XLogCtl->Insert;
|
||||
Insert->PrevRecord = LastRec;
|
||||
XLogCtl->xlblocks[0].xlogid = (openLogSegNo * XLOG_SEG_SIZE) >> 32;
|
||||
XLogCtl->xlblocks[0].xrecoff =
|
||||
((EndOfLog.xrecoff - 1) / XLOG_BLCKSZ + 1) * XLOG_BLCKSZ;
|
||||
XLogCtl->xlblocks[0] = ((EndOfLog - 1) / XLOG_BLCKSZ + 1) * XLOG_BLCKSZ;
|
||||
|
||||
/*
|
||||
* Tricky point here: readBuf contains the *last* block that the LastRec
|
||||
* record spans, not the one it starts in. The last block is indeed the
|
||||
* one we want to use.
|
||||
*/
|
||||
Assert(readOff == (XLogCtl->xlblocks[0].xrecoff - XLOG_BLCKSZ) % XLogSegSize);
|
||||
Assert(readOff == (XLogCtl->xlblocks[0] - XLOG_BLCKSZ) % XLogSegSize);
|
||||
memcpy((char *) Insert->currpage, readBuf, XLOG_BLCKSZ);
|
||||
Insert->currpos = (char *) Insert->currpage +
|
||||
(EndOfLog.xrecoff + XLOG_BLCKSZ - XLogCtl->xlblocks[0].xrecoff);
|
||||
(EndOfLog + XLOG_BLCKSZ - XLogCtl->xlblocks[0]);
|
||||
|
||||
LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
|
||||
|
||||
|
@ -7053,7 +7031,7 @@ CheckRecoveryConsistency(void)
|
|||
reachedConsistency = true;
|
||||
ereport(LOG,
|
||||
(errmsg("consistent recovery state reached at %X/%X",
|
||||
EndRecPtr.xlogid, EndRecPtr.xrecoff)));
|
||||
(uint32) (EndRecPtr >> 32), (uint32) EndRecPtr)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7212,7 +7190,7 @@ ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt)
|
|||
{
|
||||
XLogRecord *record;
|
||||
|
||||
if (!XRecOffIsValid(RecPtr.xrecoff))
|
||||
if (!XRecOffIsValid(RecPtr))
|
||||
{
|
||||
switch (whichChkpt)
|
||||
{
|
||||
|
@ -7738,13 +7716,9 @@ CreateCheckPoint(int flags)
|
|||
XLogRecPtr curInsert;
|
||||
|
||||
INSERT_RECPTR(curInsert, Insert, Insert->curridx);
|
||||
if (curInsert.xlogid == ControlFile->checkPoint.xlogid &&
|
||||
curInsert.xrecoff == ControlFile->checkPoint.xrecoff +
|
||||
if (curInsert == ControlFile->checkPoint +
|
||||
MAXALIGN(SizeOfXLogRecord + sizeof(CheckPoint)) &&
|
||||
ControlFile->checkPoint.xlogid ==
|
||||
ControlFile->checkPointCopy.redo.xlogid &&
|
||||
ControlFile->checkPoint.xrecoff ==
|
||||
ControlFile->checkPointCopy.redo.xrecoff)
|
||||
ControlFile->checkPoint == ControlFile->checkPointCopy.redo)
|
||||
{
|
||||
LWLockRelease(WALInsertLock);
|
||||
LWLockRelease(CheckpointLock);
|
||||
|
@ -8074,8 +8048,8 @@ RecoveryRestartPoint(const CheckPoint *checkPoint)
|
|||
elog(trace_recovery(DEBUG2),
|
||||
"RM %d not safe to record restart point at %X/%X",
|
||||
rmid,
|
||||
checkPoint->redo.xlogid,
|
||||
checkPoint->redo.xrecoff);
|
||||
(uint32) (checkPoint->redo >> 32),
|
||||
(uint32) checkPoint->redo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -8092,8 +8066,8 @@ RecoveryRestartPoint(const CheckPoint *checkPoint)
|
|||
elog(trace_recovery(DEBUG2),
|
||||
"could not record restart point at %X/%X because there "
|
||||
"are unresolved references to invalid pages",
|
||||
checkPoint->redo.xlogid,
|
||||
checkPoint->redo.xrecoff);
|
||||
(uint32) (checkPoint->redo >> 32),
|
||||
(uint32) checkPoint->redo);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8172,7 +8146,7 @@ CreateRestartPoint(int flags)
|
|||
{
|
||||
ereport(DEBUG2,
|
||||
(errmsg("skipping restartpoint, already performed at %X/%X",
|
||||
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff)));
|
||||
(uint32) (lastCheckPoint.redo >> 32), (uint32) lastCheckPoint.redo)));
|
||||
|
||||
UpdateMinRecoveryPoint(InvalidXLogRecPtr, true);
|
||||
if (flags & CHECKPOINT_IS_SHUTDOWN)
|
||||
|
@ -8282,7 +8256,7 @@ CreateRestartPoint(int flags)
|
|||
xtime = GetLatestXTime();
|
||||
ereport((log_checkpoints ? LOG : DEBUG2),
|
||||
(errmsg("recovery restart point at %X/%X",
|
||||
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff),
|
||||
(uint32) (lastCheckPoint.redo >> 32), (uint32) lastCheckPoint.redo),
|
||||
xtime ? errdetail("last completed transaction was at log time %s",
|
||||
timestamptz_to_str(xtime)) : 0));
|
||||
|
||||
|
@ -8408,7 +8382,7 @@ XLogRestorePoint(const char *rpName)
|
|||
|
||||
ereport(LOG,
|
||||
(errmsg("restore point \"%s\" created at %X/%X",
|
||||
rpName, RecPtr.xlogid, RecPtr.xrecoff)));
|
||||
rpName, (uint32) (RecPtr >> 32), (uint32) RecPtr)));
|
||||
|
||||
return RecPtr;
|
||||
}
|
||||
|
@ -8757,8 +8731,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
|||
* decreasing max_* settings.
|
||||
*/
|
||||
minRecoveryPoint = ControlFile->minRecoveryPoint;
|
||||
if ((minRecoveryPoint.xlogid != 0 || minRecoveryPoint.xrecoff != 0)
|
||||
&& XLByteLT(minRecoveryPoint, lsn))
|
||||
if (minRecoveryPoint != 0 && XLByteLT(minRecoveryPoint, lsn))
|
||||
{
|
||||
ControlFile->minRecoveryPoint = lsn;
|
||||
}
|
||||
|
@ -8808,7 +8781,7 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
|||
appendStringInfo(buf, "checkpoint: redo %X/%X; "
|
||||
"tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
|
||||
"oldest xid %u in DB %u; oldest running xid %u; %s",
|
||||
checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
|
||||
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
|
||||
checkpoint->ThisTimeLineID,
|
||||
checkpoint->fullPageWrites ? "true" : "false",
|
||||
checkpoint->nextXidEpoch, checkpoint->nextXid,
|
||||
|
@ -8848,7 +8821,7 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
|||
|
||||
memcpy(&startpoint, rec, sizeof(XLogRecPtr));
|
||||
appendStringInfo(buf, "backup end: %X/%X",
|
||||
startpoint.xlogid, startpoint.xrecoff);
|
||||
(uint32) (startpoint >> 32), (uint32) startpoint);
|
||||
}
|
||||
else if (info == XLOG_PARAMETER_CHANGE)
|
||||
{
|
||||
|
@ -8894,7 +8867,7 @@ xlog_outrec(StringInfo buf, XLogRecord *record)
|
|||
int i;
|
||||
|
||||
appendStringInfo(buf, "prev %X/%X; xid %u",
|
||||
record->xl_prev.xlogid, record->xl_prev.xrecoff,
|
||||
(uint32) (record->xl_prev >> 32), (uint32) record->xl_prev,
|
||||
record->xl_xid);
|
||||
|
||||
appendStringInfo(buf, "; len %u",
|
||||
|
@ -9294,9 +9267,9 @@ do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile)
|
|||
"%Y-%m-%d %H:%M:%S %Z",
|
||||
pg_localtime(&stamp_time, log_timezone));
|
||||
appendStringInfo(&labelfbuf, "START WAL LOCATION: %X/%X (file %s)\n",
|
||||
startpoint.xlogid, startpoint.xrecoff, xlogfilename);
|
||||
(uint32) (startpoint >> 32), (uint32) startpoint, xlogfilename);
|
||||
appendStringInfo(&labelfbuf, "CHECKPOINT LOCATION: %X/%X\n",
|
||||
checkpointloc.xlogid, checkpointloc.xrecoff);
|
||||
(uint32) (checkpointloc >> 32), (uint32) checkpointloc);
|
||||
appendStringInfo(&labelfbuf, "BACKUP METHOD: %s\n",
|
||||
exclusive ? "pg_start_backup" : "streamed");
|
||||
appendStringInfo(&labelfbuf, "BACKUP FROM: %s\n",
|
||||
|
@ -9416,6 +9389,8 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive)
|
|||
bool reported_waiting = false;
|
||||
char *remaining;
|
||||
char *ptr;
|
||||
uint32 hi,
|
||||
lo;
|
||||
|
||||
backup_started_in_recovery = RecoveryInProgress();
|
||||
|
||||
|
@ -9520,11 +9495,12 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive)
|
|||
* but we are not expecting any variability in the file format).
|
||||
*/
|
||||
if (sscanf(labelfile, "START WAL LOCATION: %X/%X (file %24s)%c",
|
||||
&startpoint.xlogid, &startpoint.xrecoff, startxlogfilename,
|
||||
&hi, &lo, startxlogfilename,
|
||||
&ch) != 4 || ch != '\n')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
|
||||
startpoint = ((uint64) hi) << 32 | lo;
|
||||
remaining = strchr(labelfile, '\n') + 1; /* %n is not portable enough */
|
||||
|
||||
/*
|
||||
|
@ -9632,7 +9608,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive)
|
|||
*/
|
||||
XLByteToSeg(startpoint, _logSegNo);
|
||||
BackupHistoryFilePath(histfilepath, ThisTimeLineID, _logSegNo,
|
||||
startpoint.xrecoff % XLogSegSize);
|
||||
(uint32) (startpoint % XLogSegSize));
|
||||
fp = AllocateFile(histfilepath, "w");
|
||||
if (!fp)
|
||||
ereport(ERROR,
|
||||
|
@ -9640,9 +9616,9 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive)
|
|||
errmsg("could not create file \"%s\": %m",
|
||||
histfilepath)));
|
||||
fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
|
||||
startpoint.xlogid, startpoint.xrecoff, startxlogfilename);
|
||||
(uint32) (startpoint >> 32), (uint32) startpoint, startxlogfilename);
|
||||
fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
|
||||
stoppoint.xlogid, stoppoint.xrecoff, stopxlogfilename);
|
||||
(uint32) (stoppoint >> 32), (uint32) stoppoint, stopxlogfilename);
|
||||
/* transfer remaining lines from label to history file */
|
||||
fprintf(fp, "%s", remaining);
|
||||
fprintf(fp, "STOP TIME: %s\n", strfbuf);
|
||||
|
@ -9685,7 +9661,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive)
|
|||
|
||||
XLByteToSeg(startpoint, _logSegNo);
|
||||
BackupHistoryFileName(histfilename, ThisTimeLineID, _logSegNo,
|
||||
startpoint.xrecoff % XLogSegSize);
|
||||
(uint32) (startpoint % XLogSegSize));
|
||||
|
||||
seconds_before_warning = 60;
|
||||
waits = 0;
|
||||
|
@ -9861,6 +9837,8 @@ read_backup_label(XLogRecPtr *checkPointLoc, bool *backupEndRequired,
|
|||
char ch;
|
||||
char backuptype[20];
|
||||
char backupfrom[20];
|
||||
uint32 hi,
|
||||
lo;
|
||||
|
||||
*backupEndRequired = false;
|
||||
*backupFromStandby = false;
|
||||
|
@ -9885,17 +9863,17 @@ read_backup_label(XLogRecPtr *checkPointLoc, bool *backupEndRequired,
|
|||
* format).
|
||||
*/
|
||||
if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %08X%16s)%c",
|
||||
&RedoStartLSN.xlogid, &RedoStartLSN.xrecoff, &tli,
|
||||
startxlogfilename, &ch) != 5 || ch != '\n')
|
||||
&hi, &lo, &tli, startxlogfilename, &ch) != 5 || ch != '\n')
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
|
||||
RedoStartLSN = ((uint64) hi) << 32 | lo;
|
||||
if (fscanf(lfp, "CHECKPOINT LOCATION: %X/%X%c",
|
||||
&checkPointLoc->xlogid, &checkPointLoc->xrecoff,
|
||||
&ch) != 3 || ch != '\n')
|
||||
&hi, &lo, &ch) != 3 || ch != '\n')
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
|
||||
*checkPointLoc = ((uint64) hi) << 32 | lo;
|
||||
|
||||
/*
|
||||
* BACKUP METHOD and BACKUP FROM lines are new in 9.2. We can't restore
|
||||
|
@ -10018,7 +9996,7 @@ static bool
|
|||
XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
bool randAccess)
|
||||
{
|
||||
static XLogRecPtr receivedUpto = {0, 0};
|
||||
static XLogRecPtr receivedUpto = 0;
|
||||
bool switched_segment = false;
|
||||
uint32 targetPageOff;
|
||||
uint32 targetRecOff;
|
||||
|
@ -10026,8 +10004,8 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
|||
static pg_time_t last_fail_time = 0;
|
||||
|
||||
XLByteToSeg(*RecPtr, targetSegNo);
|
||||
targetPageOff = ((RecPtr->xrecoff % XLogSegSize) / XLOG_BLCKSZ) * XLOG_BLCKSZ;
|
||||
targetRecOff = RecPtr->xrecoff % XLOG_BLCKSZ;
|
||||
targetPageOff = (((*RecPtr) % XLogSegSize) / XLOG_BLCKSZ) * XLOG_BLCKSZ;
|
||||
targetRecOff = (*RecPtr) % XLOG_BLCKSZ;
|
||||
|
||||
/* Fast exit if we have read the record in the current buffer already */
|
||||
if (failedSources == 0 && targetSegNo == readSegNo &&
|
||||
|
@ -10308,13 +10286,12 @@ retry:
|
|||
*/
|
||||
if (readSource == XLOG_FROM_STREAM)
|
||||
{
|
||||
if (RecPtr->xlogid != receivedUpto.xlogid ||
|
||||
(RecPtr->xrecoff / XLOG_BLCKSZ) != (receivedUpto.xrecoff / XLOG_BLCKSZ))
|
||||
if (((*RecPtr) / XLOG_BLCKSZ) != (receivedUpto / XLOG_BLCKSZ))
|
||||
{
|
||||
readLen = XLOG_BLCKSZ;
|
||||
}
|
||||
else
|
||||
readLen = receivedUpto.xrecoff % XLogSegSize - targetPageOff;
|
||||
readLen = receivedUpto % XLogSegSize - targetPageOff;
|
||||
}
|
||||
else
|
||||
readLen = XLOG_BLCKSZ;
|
||||
|
@ -10420,7 +10397,7 @@ triggered:
|
|||
static int
|
||||
emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
|
||||
{
|
||||
static XLogRecPtr lastComplaint = {0, 0};
|
||||
static XLogRecPtr lastComplaint = 0;
|
||||
|
||||
if (readSource == XLOG_FROM_PG_XLOG && emode == LOG)
|
||||
{
|
||||
|
|
|
@ -57,7 +57,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
|
|||
startpoint = do_pg_start_backup(backupidstr, fast, NULL);
|
||||
|
||||
snprintf(startxlogstr, sizeof(startxlogstr), "%X/%X",
|
||||
startpoint.xlogid, startpoint.xrecoff);
|
||||
(uint32) (startpoint >> 32), (uint32) startpoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(startxlogstr));
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
|||
stoppoint = do_pg_stop_backup(NULL, true);
|
||||
|
||||
snprintf(stopxlogstr, sizeof(stopxlogstr), "%X/%X",
|
||||
stoppoint.xlogid, stoppoint.xrecoff);
|
||||
(uint32) (stoppoint >> 32), (uint32) stoppoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(stopxlogstr));
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
|
|||
* As a convenience, return the WAL location of the switch record
|
||||
*/
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
switchpoint.xlogid, switchpoint.xrecoff);
|
||||
(uint32) (switchpoint >> 32), (uint32) switchpoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ pg_create_restore_point(PG_FUNCTION_ARGS)
|
|||
* As a convenience, return the WAL location of the restore point record
|
||||
*/
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
restorepoint.xlogid, restorepoint.xrecoff);
|
||||
(uint32) (restorepoint >> 32), (uint32) restorepoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ pg_current_xlog_location(PG_FUNCTION_ARGS)
|
|||
current_recptr = GetXLogWriteRecPtr();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
current_recptr.xlogid, current_recptr.xrecoff);
|
||||
(uint32) (current_recptr >> 32), (uint32) current_recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
|
|||
current_recptr = GetXLogInsertRecPtr();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
current_recptr.xlogid, current_recptr.xrecoff);
|
||||
(uint32) (current_recptr >> 32), (uint32) current_recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
}
|
||||
|
||||
|
@ -226,11 +226,11 @@ pg_last_xlog_receive_location(PG_FUNCTION_ARGS)
|
|||
|
||||
recptr = GetWalRcvWriteRecPtr(NULL);
|
||||
|
||||
if (recptr.xlogid == 0 && recptr.xrecoff == 0)
|
||||
if (recptr == 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
recptr.xlogid, recptr.xrecoff);
|
||||
(uint32) (recptr >> 32), (uint32) recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
}
|
||||
|
||||
|
@ -248,11 +248,11 @@ pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
|
|||
|
||||
recptr = GetXLogReplayRecPtr(NULL);
|
||||
|
||||
if (recptr.xlogid == 0 && recptr.xrecoff == 0)
|
||||
if (recptr == 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
recptr.xlogid, recptr.xrecoff);
|
||||
(uint32) (recptr >> 32), (uint32) recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
}
|
||||
|
||||
|
@ -269,8 +269,8 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
|||
{
|
||||
text *location = PG_GETARG_TEXT_P(0);
|
||||
char *locationstr;
|
||||
unsigned int uxlogid;
|
||||
unsigned int uxrecoff;
|
||||
uint32 hi,
|
||||
lo;
|
||||
XLogSegNo xlogsegno;
|
||||
uint32 xrecoff;
|
||||
XLogRecPtr locationpoint;
|
||||
|
@ -294,14 +294,12 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
|||
|
||||
validate_xlog_location(locationstr);
|
||||
|
||||
if (sscanf(locationstr, "%X/%X", &uxlogid, &uxrecoff) != 2)
|
||||
if (sscanf(locationstr, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"",
|
||||
locationstr)));
|
||||
|
||||
locationpoint.xlogid = uxlogid;
|
||||
locationpoint.xrecoff = uxrecoff;
|
||||
locationpoint = ((uint64) hi) << 32 | lo;
|
||||
|
||||
/*
|
||||
* Construct a tuple descriptor for the result row. This must match this
|
||||
|
@ -327,7 +325,7 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
|||
/*
|
||||
* offset
|
||||
*/
|
||||
xrecoff = locationpoint.xrecoff % XLogSegSize;
|
||||
xrecoff = locationpoint % XLogSegSize;
|
||||
|
||||
values[1] = UInt32GetDatum(xrecoff);
|
||||
isnull[1] = false;
|
||||
|
@ -351,8 +349,8 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
|
|||
{
|
||||
text *location = PG_GETARG_TEXT_P(0);
|
||||
char *locationstr;
|
||||
unsigned int uxlogid;
|
||||
unsigned int uxrecoff;
|
||||
uint32 hi,
|
||||
lo;
|
||||
XLogSegNo xlogsegno;
|
||||
XLogRecPtr locationpoint;
|
||||
char xlogfilename[MAXFNAMELEN];
|
||||
|
@ -367,14 +365,12 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
|
|||
|
||||
validate_xlog_location(locationstr);
|
||||
|
||||
if (sscanf(locationstr, "%X/%X", &uxlogid, &uxrecoff) != 2)
|
||||
if (sscanf(locationstr, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"",
|
||||
locationstr)));
|
||||
|
||||
locationpoint.xlogid = uxlogid;
|
||||
locationpoint.xrecoff = uxrecoff;
|
||||
locationpoint = ((uint64) hi) << 32 | lo;
|
||||
|
||||
XLByteToPrevSeg(locationpoint, xlogsegno);
|
||||
XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno);
|
||||
|
@ -514,6 +510,8 @@ pg_xlog_location_diff(PG_FUNCTION_ARGS)
|
|||
Numeric result;
|
||||
uint64 bytes1,
|
||||
bytes2;
|
||||
uint32 hi,
|
||||
lo;
|
||||
|
||||
/*
|
||||
* Read and parse input
|
||||
|
@ -524,17 +522,20 @@ pg_xlog_location_diff(PG_FUNCTION_ARGS)
|
|||
validate_xlog_location(str1);
|
||||
validate_xlog_location(str2);
|
||||
|
||||
if (sscanf(str1, "%X/%X", &loc1.xlogid, &loc1.xrecoff) != 2)
|
||||
if (sscanf(str1, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"", str1)));
|
||||
if (sscanf(str2, "%X/%X", &loc2.xlogid, &loc2.xrecoff) != 2)
|
||||
loc1 = ((uint64) hi) << 32 | lo;
|
||||
|
||||
if (sscanf(str2, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"", str2)));
|
||||
loc2 = ((uint64) hi) << 32 | lo;
|
||||
|
||||
bytes1 = (((uint64)loc1.xlogid) << 32L) + loc1.xrecoff;
|
||||
bytes2 = (((uint64)loc2.xlogid) << 32L) + loc2.xrecoff;
|
||||
bytes1 = (uint64) loc1;
|
||||
bytes2 = (uint64) loc2;
|
||||
|
||||
/*
|
||||
* result = bytes1 - bytes2.
|
||||
|
|
|
@ -631,7 +631,7 @@ CheckArchiveTimeout(void)
|
|||
* If the returned pointer points exactly to a segment boundary,
|
||||
* assume nothing happened.
|
||||
*/
|
||||
if ((switchpoint.xrecoff % XLogSegSize) != 0)
|
||||
if ((switchpoint % XLogSegSize) != 0)
|
||||
ereport(DEBUG1,
|
||||
(errmsg("transaction log switch forced (archive_timeout=%d)",
|
||||
XLogArchiveTimeout)));
|
||||
|
@ -778,10 +778,7 @@ IsCheckpointOnSchedule(double progress)
|
|||
if (!RecoveryInProgress())
|
||||
{
|
||||
recptr = GetInsertRecPtr();
|
||||
elapsed_xlogs =
|
||||
(((double) ((uint64) (recptr.xlogid - ckpt_start_recptr.xlogid) << 32L)) +
|
||||
((double) recptr.xrecoff - (double) ckpt_start_recptr.xrecoff) / XLogSegSize) /
|
||||
CheckPointSegments;
|
||||
elapsed_xlogs = (((double) (recptr - ckpt_start_recptr)) / XLogSegSize) / CheckPointSegments;
|
||||
|
||||
if (progress < elapsed_xlogs)
|
||||
{
|
||||
|
|
|
@ -497,7 +497,7 @@ SendXlogRecPtrResult(XLogRecPtr ptr)
|
|||
StringInfoData buf;
|
||||
char str[MAXFNAMELEN];
|
||||
|
||||
snprintf(str, sizeof(str), "%X/%X", ptr.xlogid, ptr.xrecoff);
|
||||
snprintf(str, sizeof(str), "%X/%X", (uint32) (ptr >> 32), (uint32) ptr);
|
||||
|
||||
pq_beginmessage(&buf, 'T'); /* RowDescription */
|
||||
pq_sendint(&buf, 1, 2); /* 1 field */
|
||||
|
|
|
@ -156,7 +156,7 @@ libpqrcv_connect(char *conninfo, XLogRecPtr startpoint)
|
|||
|
||||
/* Start streaming from the point requested by startup process */
|
||||
snprintf(cmd, sizeof(cmd), "START_REPLICATION %X/%X",
|
||||
startpoint.xlogid, startpoint.xrecoff);
|
||||
(uint32) (startpoint >> 32), (uint32) startpoint);
|
||||
res = libpqrcv_PQexec(cmd);
|
||||
if (PQresultStatus(res) != PGRES_COPY_BOTH)
|
||||
{
|
||||
|
|
|
@ -72,8 +72,11 @@ START_REPLICATION { return K_START_REPLICATION; }
|
|||
" " ;
|
||||
|
||||
{hexdigit}+\/{hexdigit}+ {
|
||||
if (sscanf(yytext, "%X/%X", &yylval.recptr.xlogid, &yylval.recptr.xrecoff) != 2)
|
||||
uint32 hi,
|
||||
lo;
|
||||
if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
|
||||
yyerror("invalid streaming start location");
|
||||
yylval.recptr = ((uint64) hi) << 32 | lo;
|
||||
return RECPTR;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
|
|||
new_status = (char *) palloc(len + 32 + 1);
|
||||
memcpy(new_status, old_status, len);
|
||||
sprintf(new_status + len, " waiting for %X/%X",
|
||||
XactCommitLSN.xlogid, XactCommitLSN.xrecoff);
|
||||
(uint32) (XactCommitLSN >> 32), (uint32) XactCommitLSN);
|
||||
set_ps_display(new_status, false);
|
||||
new_status[len] = '\0'; /* truncate off " waiting ..." */
|
||||
}
|
||||
|
@ -255,8 +255,7 @@ SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
|
|||
*/
|
||||
Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
|
||||
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
|
||||
MyProc->waitLSN.xlogid = 0;
|
||||
MyProc->waitLSN.xrecoff = 0;
|
||||
MyProc->waitLSN = 0;
|
||||
|
||||
if (new_status)
|
||||
{
|
||||
|
@ -440,12 +439,8 @@ SyncRepReleaseWaiters(void)
|
|||
LWLockRelease(SyncRepLock);
|
||||
|
||||
elog(DEBUG3, "released %d procs up to write %X/%X, %d procs up to flush %X/%X",
|
||||
numwrite,
|
||||
MyWalSnd->write.xlogid,
|
||||
MyWalSnd->write.xrecoff,
|
||||
numflush,
|
||||
MyWalSnd->flush.xlogid,
|
||||
MyWalSnd->flush.xrecoff);
|
||||
numwrite, (uint32) (MyWalSnd->write >> 32), (uint32) MyWalSnd->write,
|
||||
numflush, (uint32) (MyWalSnd->flush >> 32), (uint32) MyWalSnd->flush);
|
||||
|
||||
/*
|
||||
* If we are managing the highest priority standby, though we weren't
|
||||
|
@ -630,8 +625,7 @@ SyncRepQueueIsOrderedByLSN(int mode)
|
|||
|
||||
Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
|
||||
|
||||
lastLSN.xlogid = 0;
|
||||
lastLSN.xrecoff = 0;
|
||||
lastLSN = 0;
|
||||
|
||||
proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]),
|
||||
&(WalSndCtl->SyncRepQueue[mode]),
|
||||
|
|
|
@ -516,7 +516,7 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
|
|||
}
|
||||
|
||||
/* Calculate the start offset of the received logs */
|
||||
startoff = recptr.xrecoff % XLogSegSize;
|
||||
startoff = recptr % XLogSegSize;
|
||||
|
||||
if (startoff + nbytes > XLogSegSize)
|
||||
segbytes = XLogSegSize - startoff;
|
||||
|
@ -601,8 +601,8 @@ XLogWalRcvFlush(bool dying)
|
|||
char activitymsg[50];
|
||||
|
||||
snprintf(activitymsg, sizeof(activitymsg), "streaming %X/%X",
|
||||
LogstreamResult.Write.xlogid,
|
||||
LogstreamResult.Write.xrecoff);
|
||||
(uint32) (LogstreamResult.Write >> 32),
|
||||
(uint32) LogstreamResult.Write);
|
||||
set_ps_display(activitymsg, false);
|
||||
}
|
||||
|
||||
|
@ -657,9 +657,9 @@ XLogWalRcvSendReply(void)
|
|||
reply_message.sendTime = now;
|
||||
|
||||
elog(DEBUG2, "sending write %X/%X flush %X/%X apply %X/%X",
|
||||
reply_message.write.xlogid, reply_message.write.xrecoff,
|
||||
reply_message.flush.xlogid, reply_message.flush.xrecoff,
|
||||
reply_message.apply.xlogid, reply_message.apply.xrecoff);
|
||||
(uint32) (reply_message.write >> 32), (uint32) reply_message.write,
|
||||
(uint32) (reply_message.flush >> 32), (uint32) reply_message.flush,
|
||||
(uint32) (reply_message.apply >> 32), (uint32) reply_message.apply);
|
||||
|
||||
/* Prepend with the message type and send it. */
|
||||
buf[0] = 'r';
|
||||
|
|
|
@ -185,8 +185,8 @@ RequestXLogStreaming(XLogRecPtr recptr, const char *conninfo)
|
|||
* being created by XLOG streaming, which might cause trouble later on if
|
||||
* the segment is e.g archived.
|
||||
*/
|
||||
if (recptr.xrecoff % XLogSegSize != 0)
|
||||
recptr.xrecoff -= recptr.xrecoff % XLogSegSize;
|
||||
if (recptr % XLogSegSize != 0)
|
||||
recptr -= recptr % XLogSegSize;
|
||||
|
||||
SpinLockAcquire(&walrcv->mutex);
|
||||
|
||||
|
@ -204,8 +204,7 @@ RequestXLogStreaming(XLogRecPtr recptr, const char *conninfo)
|
|||
* If this is the first startup of walreceiver, we initialize receivedUpto
|
||||
* and latestChunkStart to receiveStart.
|
||||
*/
|
||||
if (walrcv->receiveStart.xlogid == 0 &&
|
||||
walrcv->receiveStart.xrecoff == 0)
|
||||
if (walrcv->receiveStart == 0)
|
||||
{
|
||||
walrcv->receivedUpto = recptr;
|
||||
walrcv->latestChunkStart = recptr;
|
||||
|
|
|
@ -94,7 +94,7 @@ static uint32 sendOff = 0;
|
|||
* How far have we sent WAL already? This is also advertised in
|
||||
* MyWalSnd->sentPtr. (Actually, this is the next WAL location to send.)
|
||||
*/
|
||||
static XLogRecPtr sentPtr = {0, 0};
|
||||
static XLogRecPtr sentPtr = 0;
|
||||
|
||||
/*
|
||||
* Buffer for processing reply messages.
|
||||
|
@ -300,8 +300,7 @@ IdentifySystem(void)
|
|||
|
||||
logptr = am_cascading_walsender ? GetStandbyFlushRecPtr() : GetInsertRecPtr();
|
||||
|
||||
snprintf(xpos, sizeof(xpos), "%X/%X",
|
||||
logptr.xlogid, logptr.xrecoff);
|
||||
snprintf(xpos, sizeof(xpos), "%X/%X", (uint32) (logptr >> 32), (uint32) logptr);
|
||||
|
||||
/* Send a RowDescription message */
|
||||
pq_beginmessage(&buf, 'T');
|
||||
|
@ -613,9 +612,9 @@ ProcessStandbyReplyMessage(void)
|
|||
pq_copymsgbytes(&reply_message, (char *) &reply, sizeof(StandbyReplyMessage));
|
||||
|
||||
elog(DEBUG2, "write %X/%X flush %X/%X apply %X/%X",
|
||||
reply.write.xlogid, reply.write.xrecoff,
|
||||
reply.flush.xlogid, reply.flush.xrecoff,
|
||||
reply.apply.xlogid, reply.apply.xrecoff);
|
||||
(uint32) (reply.write << 32), (uint32) reply.write,
|
||||
(uint32) (reply.flush << 32), (uint32) reply.flush,
|
||||
(uint32) (reply.apply << 32), (uint32) reply.apply);
|
||||
|
||||
/*
|
||||
* Update shared state for this WalSender process based on reply data from
|
||||
|
@ -990,7 +989,7 @@ retry:
|
|||
int segbytes;
|
||||
int readbytes;
|
||||
|
||||
startoff = recptr.xrecoff % XLogSegSize;
|
||||
startoff = recptr % XLogSegSize;
|
||||
|
||||
if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo))
|
||||
{
|
||||
|
@ -1156,12 +1155,6 @@ XLogSend(char *msgbuf, bool *caughtup)
|
|||
startptr = sentPtr;
|
||||
endptr = startptr;
|
||||
XLByteAdvance(endptr, MAX_SEND_SIZE);
|
||||
if (endptr.xlogid != startptr.xlogid)
|
||||
{
|
||||
/* Don't cross a logfile boundary within one message */
|
||||
Assert(endptr.xlogid == startptr.xlogid + 1);
|
||||
endptr.xrecoff = 0;
|
||||
}
|
||||
|
||||
/* if we went beyond SendRqstPtr, back off */
|
||||
if (XLByteLE(SendRqstPtr, endptr))
|
||||
|
@ -1172,14 +1165,11 @@ XLogSend(char *msgbuf, bool *caughtup)
|
|||
else
|
||||
{
|
||||
/* round down to page boundary. */
|
||||
endptr.xrecoff -= (endptr.xrecoff % XLOG_BLCKSZ);
|
||||
endptr -= (endptr % XLOG_BLCKSZ);
|
||||
*caughtup = false;
|
||||
}
|
||||
|
||||
if (endptr.xrecoff == 0)
|
||||
nbytes = 0x100000000L - (uint64) startptr.xrecoff;
|
||||
else
|
||||
nbytes = endptr.xrecoff - startptr.xrecoff;
|
||||
nbytes = endptr - startptr;
|
||||
Assert(nbytes <= MAX_SEND_SIZE);
|
||||
|
||||
/*
|
||||
|
@ -1223,7 +1213,7 @@ XLogSend(char *msgbuf, bool *caughtup)
|
|||
char activitymsg[50];
|
||||
|
||||
snprintf(activitymsg, sizeof(activitymsg), "streaming %X/%X",
|
||||
sentPtr.xlogid, sentPtr.xrecoff);
|
||||
(uint32) (sentPtr >> 32), (uint32) sentPtr);
|
||||
set_ps_display(activitymsg, false);
|
||||
}
|
||||
|
||||
|
@ -1565,25 +1555,25 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
|
|||
values[1] = CStringGetTextDatum(WalSndGetStateString(state));
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
sentPtr.xlogid, sentPtr.xrecoff);
|
||||
(uint32) (sentPtr >> 32), (uint32) sentPtr);
|
||||
values[2] = CStringGetTextDatum(location);
|
||||
|
||||
if (write.xlogid == 0 && write.xrecoff == 0)
|
||||
if (write == 0)
|
||||
nulls[3] = true;
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
write.xlogid, write.xrecoff);
|
||||
(uint32) (write >> 32), (uint32) write);
|
||||
values[3] = CStringGetTextDatum(location);
|
||||
|
||||
if (flush.xlogid == 0 && flush.xrecoff == 0)
|
||||
if (flush == 0)
|
||||
nulls[4] = true;
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
flush.xlogid, flush.xrecoff);
|
||||
(uint32) (flush >> 32), (uint32) flush);
|
||||
values[4] = CStringGetTextDatum(location);
|
||||
|
||||
if (apply.xlogid == 0 && apply.xrecoff == 0)
|
||||
if (apply == 0)
|
||||
nulls[5] = true;
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
apply.xlogid, apply.xrecoff);
|
||||
(uint32) (apply >> 32), (uint32) apply);
|
||||
values[5] = CStringGetTextDatum(location);
|
||||
|
||||
values[6] = Int32GetDatum(sync_priority[i]);
|
||||
|
|
|
@ -936,7 +936,7 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
|
|||
elog(trace_recovery(DEBUG2),
|
||||
"snapshot of %u running transactions overflowed (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
|
||||
CurrRunningXacts->xcnt,
|
||||
recptr.xlogid, recptr.xrecoff,
|
||||
(uint32) (recptr >> 32), (uint32) recptr,
|
||||
CurrRunningXacts->oldestRunningXid,
|
||||
CurrRunningXacts->latestCompletedXid,
|
||||
CurrRunningXacts->nextXid);
|
||||
|
@ -944,7 +944,7 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
|
|||
elog(trace_recovery(DEBUG2),
|
||||
"snapshot of %u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
|
||||
CurrRunningXacts->xcnt,
|
||||
recptr.xlogid, recptr.xrecoff,
|
||||
(uint32) (recptr >> 32), (uint32) recptr,
|
||||
CurrRunningXacts->oldestRunningXid,
|
||||
CurrRunningXacts->latestCompletedXid,
|
||||
CurrRunningXacts->nextXid);
|
||||
|
|
|
@ -376,8 +376,7 @@ InitProcess(void)
|
|||
MyProc->recoveryConflictPending = false;
|
||||
|
||||
/* Initialize fields for sync rep */
|
||||
MyProc->waitLSN.xlogid = 0;
|
||||
MyProc->waitLSN.xrecoff = 0;
|
||||
MyProc->waitLSN = 0;
|
||||
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
|
||||
SHMQueueElemInit(&(MyProc->syncRepLinks));
|
||||
|
||||
|
|
|
@ -162,6 +162,8 @@ reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finishe
|
|||
if (r == 1)
|
||||
{
|
||||
char xlogend[64];
|
||||
uint32 hi,
|
||||
lo;
|
||||
|
||||
MemSet(xlogend, 0, sizeof(xlogend));
|
||||
r = read(bgpipe[0], xlogend, sizeof(xlogend));
|
||||
|
@ -172,12 +174,13 @@ reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finishe
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (sscanf(xlogend, "%X/%X", &xlogendptr.xlogid, &xlogendptr.xrecoff) != 2)
|
||||
if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
|
||||
{
|
||||
fprintf(stderr, _("%s: could not parse xlog end position \"%s\"\n"),
|
||||
progname, xlogend);
|
||||
exit(1);
|
||||
}
|
||||
xlogendptr = ((uint64) hi) << 32 | lo;
|
||||
has_xlogendptr = 1;
|
||||
|
||||
/*
|
||||
|
@ -207,9 +210,7 @@ reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finishe
|
|||
* At this point we have an end pointer, so compare it to the current
|
||||
* position to figure out if it's time to stop.
|
||||
*/
|
||||
if (segendpos.xlogid > xlogendptr.xlogid ||
|
||||
(segendpos.xlogid == xlogendptr.xlogid &&
|
||||
segendpos.xrecoff >= xlogendptr.xrecoff))
|
||||
if (segendpos >= xlogendptr)
|
||||
return true;
|
||||
|
||||
/*
|
||||
|
@ -255,20 +256,23 @@ static void
|
|||
StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
|
||||
{
|
||||
logstreamer_param *param;
|
||||
uint32 hi,
|
||||
lo;
|
||||
|
||||
param = xmalloc0(sizeof(logstreamer_param));
|
||||
param->timeline = timeline;
|
||||
param->sysidentifier = sysidentifier;
|
||||
|
||||
/* Convert the starting position */
|
||||
if (sscanf(startpos, "%X/%X", ¶m->startptr.xlogid, ¶m->startptr.xrecoff) != 2)
|
||||
if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
|
||||
{
|
||||
fprintf(stderr, _("%s: invalid format of xlog location: %s\n"),
|
||||
progname, startpos);
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
param->startptr = ((uint64) hi) << 32 | lo;
|
||||
/* Round off to even segment position */
|
||||
param->startptr.xrecoff -= param->startptr.xrecoff % XLOG_SEG_SIZE;
|
||||
param->startptr -= param->startptr % XLOG_SEG_SIZE;
|
||||
|
||||
#ifndef WIN32
|
||||
/* Create our background pipe */
|
||||
|
|
|
@ -77,7 +77,9 @@ stop_streaming(XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
|
|||
{
|
||||
if (verbose && segment_finished)
|
||||
fprintf(stderr, _("%s: finished segment at %X/%X (timeline %u)\n"),
|
||||
progname, segendpos.xlogid, segendpos.xrecoff, timeline);
|
||||
progname,
|
||||
(uint32) (segendpos >> 32), (uint32) segendpos,
|
||||
timeline);
|
||||
|
||||
if (time_to_abort)
|
||||
{
|
||||
|
@ -212,6 +214,8 @@ StreamLog(void)
|
|||
PGresult *res;
|
||||
uint32 timeline;
|
||||
XLogRecPtr startpos;
|
||||
uint32 hi,
|
||||
lo;
|
||||
|
||||
/*
|
||||
* Connect in replication mode to the server
|
||||
|
@ -239,12 +243,13 @@ StreamLog(void)
|
|||
disconnect_and_exit(1);
|
||||
}
|
||||
timeline = atoi(PQgetvalue(res, 0, 1));
|
||||
if (sscanf(PQgetvalue(res, 0, 2), "%X/%X", &startpos.xlogid, &startpos.xrecoff) != 2)
|
||||
if (sscanf(PQgetvalue(res, 0, 2), "%X/%X", &hi, &lo) != 2)
|
||||
{
|
||||
fprintf(stderr, _("%s: could not parse log start position from value \"%s\"\n"),
|
||||
progname, PQgetvalue(res, 0, 2));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
startpos = ((uint64) hi) << 32 | lo;
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
|
@ -255,14 +260,16 @@ StreamLog(void)
|
|||
/*
|
||||
* Always start streaming at the beginning of a segment
|
||||
*/
|
||||
startpos.xrecoff -= startpos.xrecoff % XLOG_SEG_SIZE;
|
||||
startpos -= startpos % XLOG_SEG_SIZE;
|
||||
|
||||
/*
|
||||
* Start the replication
|
||||
*/
|
||||
if (verbose)
|
||||
fprintf(stderr, _("%s: starting log streaming at %X/%X (timeline %u)\n"),
|
||||
progname, startpos.xlogid, startpos.xrecoff, timeline);
|
||||
progname,
|
||||
(uint32) (startpos >> 32), (uint32) startpos,
|
||||
timeline);
|
||||
|
||||
ReceiveXlogStream(conn, startpos, timeline, NULL, basedir,
|
||||
stop_streaming,
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
#define STREAMING_HEADER_SIZE (1+sizeof(WalDataMessageHeader))
|
||||
#define STREAMING_KEEPALIVE_SIZE (1+sizeof(PrimaryKeepaliveMessage))
|
||||
|
||||
const XLogRecPtr InvalidXLogRecPtr = {0, 0};
|
||||
|
||||
/*
|
||||
* Open a new WAL file in the specified directory. Store the name
|
||||
* (not including the full directory) in namebuf. Assumes there is
|
||||
|
@ -310,7 +308,8 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
|
|||
}
|
||||
|
||||
/* Initiate the replication stream at specified location */
|
||||
snprintf(query, sizeof(query), "START_REPLICATION %X/%X", startpos.xlogid, startpos.xrecoff);
|
||||
snprintf(query, sizeof(query), "START_REPLICATION %X/%X",
|
||||
(uint32) (startpos >> 32), (uint32) startpos);
|
||||
res = PQexec(conn, query);
|
||||
if (PQresultStatus(res) != PGRES_COPY_BOTH)
|
||||
{
|
||||
|
@ -471,7 +470,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
|
|||
|
||||
/* Extract WAL location for this block */
|
||||
memcpy(&blockpos, copybuf + 1, 8);
|
||||
xlogoff = blockpos.xrecoff % XLOG_SEG_SIZE;
|
||||
xlogoff = blockpos % XLOG_SEG_SIZE;
|
||||
|
||||
/*
|
||||
* Verify that the initial location in the stream matches where we
|
||||
|
@ -543,7 +542,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
|
|||
xlogoff += bytes_to_write;
|
||||
|
||||
/* Did we reach the end of a WAL segment? */
|
||||
if (blockpos.xrecoff % XLOG_SEG_SIZE == 0)
|
||||
if (blockpos % XLOG_SEG_SIZE == 0)
|
||||
{
|
||||
if (!close_walfile(walfile, basedir, current_walfile_name, false))
|
||||
/* Error message written in close_walfile() */
|
||||
|
|
|
@ -193,14 +193,14 @@ main(int argc, char *argv[])
|
|||
printf(_("pg_control last modified: %s\n"),
|
||||
pgctime_str);
|
||||
printf(_("Latest checkpoint location: %X/%X\n"),
|
||||
ControlFile.checkPoint.xlogid,
|
||||
ControlFile.checkPoint.xrecoff);
|
||||
(uint32) (ControlFile.checkPoint >> 32),
|
||||
(uint32) ControlFile.checkPoint);
|
||||
printf(_("Prior checkpoint location: %X/%X\n"),
|
||||
ControlFile.prevCheckPoint.xlogid,
|
||||
ControlFile.prevCheckPoint.xrecoff);
|
||||
(uint32) (ControlFile.prevCheckPoint >> 32),
|
||||
(uint32) ControlFile.prevCheckPoint);
|
||||
printf(_("Latest checkpoint's REDO location: %X/%X\n"),
|
||||
ControlFile.checkPointCopy.redo.xlogid,
|
||||
ControlFile.checkPointCopy.redo.xrecoff);
|
||||
(uint32) (ControlFile.checkPointCopy.redo >> 32),
|
||||
(uint32) ControlFile.checkPointCopy.redo);
|
||||
printf(_("Latest checkpoint's TimeLineID: %u\n"),
|
||||
ControlFile.checkPointCopy.ThisTimeLineID);
|
||||
printf(_("Latest checkpoint's full_page_writes: %s\n"),
|
||||
|
@ -223,14 +223,14 @@ main(int argc, char *argv[])
|
|||
printf(_("Time of latest checkpoint: %s\n"),
|
||||
ckpttime_str);
|
||||
printf(_("Minimum recovery ending location: %X/%X\n"),
|
||||
ControlFile.minRecoveryPoint.xlogid,
|
||||
ControlFile.minRecoveryPoint.xrecoff);
|
||||
(uint32) (ControlFile.minRecoveryPoint >> 32),
|
||||
(uint32) ControlFile.minRecoveryPoint);
|
||||
printf(_("Backup start location: %X/%X\n"),
|
||||
ControlFile.backupStartPoint.xlogid,
|
||||
ControlFile.backupStartPoint.xrecoff);
|
||||
(uint32) (ControlFile.backupStartPoint >> 32),
|
||||
(uint32) ControlFile.backupStartPoint);
|
||||
printf(_("Backup end location: %X/%X\n"),
|
||||
ControlFile.backupEndPoint.xlogid,
|
||||
ControlFile.backupEndPoint.xrecoff);
|
||||
(uint32) (ControlFile.backupEndPoint >> 32),
|
||||
(uint32) ControlFile.backupEndPoint);
|
||||
printf(_("End-of-backup record required: %s\n"),
|
||||
ControlFile.backupEndRequired ? _("yes") : _("no"));
|
||||
printf(_("Current wal_level setting: %s\n"),
|
||||
|
|
|
@ -463,8 +463,7 @@ GuessControlValues(void)
|
|||
|
||||
ControlFile.system_identifier = sysidentifier;
|
||||
|
||||
ControlFile.checkPointCopy.redo.xlogid = 0;
|
||||
ControlFile.checkPointCopy.redo.xrecoff = SizeOfXLogLongPHD;
|
||||
ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
|
||||
ControlFile.checkPointCopy.ThisTimeLineID = 1;
|
||||
ControlFile.checkPointCopy.fullPageWrites = false;
|
||||
ControlFile.checkPointCopy.nextXidEpoch = 0;
|
||||
|
@ -611,14 +610,10 @@ RewriteControlFile(void)
|
|||
ControlFile.state = DB_SHUTDOWNED;
|
||||
ControlFile.time = (pg_time_t) time(NULL);
|
||||
ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
|
||||
ControlFile.prevCheckPoint.xlogid = 0;
|
||||
ControlFile.prevCheckPoint.xrecoff = 0;
|
||||
ControlFile.minRecoveryPoint.xlogid = 0;
|
||||
ControlFile.minRecoveryPoint.xrecoff = 0;
|
||||
ControlFile.backupStartPoint.xlogid = 0;
|
||||
ControlFile.backupStartPoint.xrecoff = 0;
|
||||
ControlFile.backupEndPoint.xlogid = 0;
|
||||
ControlFile.backupEndPoint.xrecoff = 0;
|
||||
ControlFile.prevCheckPoint = 0;
|
||||
ControlFile.minRecoveryPoint = 0;
|
||||
ControlFile.backupStartPoint = 0;
|
||||
ControlFile.backupEndPoint = 0;
|
||||
ControlFile.backupEndRequired = false;
|
||||
|
||||
/*
|
||||
|
@ -714,8 +709,7 @@ FindEndOfXLOG(void)
|
|||
* numbering according to the old xlog seg size.
|
||||
*/
|
||||
segs_per_xlogid = (0x100000000L / ControlFile.xlog_seg_size);
|
||||
newXlogSegNo = ((uint64) ControlFile.checkPointCopy.redo.xlogid) * segs_per_xlogid
|
||||
+ (ControlFile.checkPointCopy.redo.xrecoff / ControlFile.xlog_seg_size);
|
||||
newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
|
||||
|
||||
/*
|
||||
* Scan the pg_xlog directory to find existing WAL segment files. We
|
||||
|
@ -919,10 +913,7 @@ WriteEmptyXLOG(void)
|
|||
page->xlp_magic = XLOG_PAGE_MAGIC;
|
||||
page->xlp_info = XLP_LONG_HEADER;
|
||||
page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
|
||||
page->xlp_pageaddr.xlogid =
|
||||
ControlFile.checkPointCopy.redo.xlogid;
|
||||
page->xlp_pageaddr.xrecoff =
|
||||
ControlFile.checkPointCopy.redo.xrecoff - SizeOfXLogLongPHD;
|
||||
page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
|
||||
longpage = (XLogLongPageHeader) page;
|
||||
longpage->xlp_sysid = ControlFile.system_identifier;
|
||||
longpage->xlp_seg_size = XLogSegSize;
|
||||
|
@ -930,8 +921,7 @@ WriteEmptyXLOG(void)
|
|||
|
||||
/* Insert the initial checkpoint record */
|
||||
record = (XLogRecord *) ((char *) page + SizeOfXLogLongPHD);
|
||||
record->xl_prev.xlogid = 0;
|
||||
record->xl_prev.xrecoff = 0;
|
||||
record->xl_prev = 0;
|
||||
record->xl_xid = InvalidTransactionId;
|
||||
record->xl_tot_len = SizeOfXLogRecord + sizeof(CheckPoint);
|
||||
record->xl_len = sizeof(CheckPoint);
|
||||
|
|
|
@ -139,10 +139,6 @@ extern bool TransactionStartedDuringRecovery(void);
|
|||
/* in transam/varsup.c */
|
||||
extern PGDLLIMPORT VariableCache ShmemVariableCache;
|
||||
|
||||
/* in transam/transam.c */
|
||||
extern const XLogRecPtr InvalidXLogRecPtr;
|
||||
|
||||
|
||||
/*
|
||||
* prototypes for functions in transam/transam.c
|
||||
*/
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef struct BkpBlock
|
|||
/*
|
||||
* Each page of XLOG file has a header like this:
|
||||
*/
|
||||
#define XLOG_PAGE_MAGIC 0xD074 /* can be used as WAL version indicator */
|
||||
#define XLOG_PAGE_MAGIC 0xD075 /* can be used as WAL version indicator */
|
||||
|
||||
typedef struct XLogPageHeaderData
|
||||
{
|
||||
|
@ -113,10 +113,7 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
|
|||
#define XLogSegmentsPerXLogId (0x100000000L / XLOG_SEG_SIZE)
|
||||
|
||||
#define XLogSegNoOffsetToRecPtr(segno, offset, dest) \
|
||||
do { \
|
||||
(dest).xlogid = (segno) / XLogSegmentsPerXLogId; \
|
||||
(dest).xrecoff = ((segno) % XLogSegmentsPerXLogId) * XLOG_SEG_SIZE + (offset); \
|
||||
} while (0)
|
||||
(dest) = (segno) * XLOG_SEG_SIZE + (offset)
|
||||
|
||||
/*
|
||||
* Macros for manipulating XLOG pointers
|
||||
|
@ -125,8 +122,8 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
|
|||
/* Align a record pointer to next page */
|
||||
#define NextLogPage(recptr) \
|
||||
do { \
|
||||
if ((recptr).xrecoff % XLOG_BLCKSZ != 0) \
|
||||
XLByteAdvance(recptr, (XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ)); \
|
||||
if ((recptr) % XLOG_BLCKSZ != 0) \
|
||||
XLByteAdvance(recptr, (XLOG_BLCKSZ - (recptr) % XLOG_BLCKSZ)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
@ -135,14 +132,13 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
|
|||
* For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
|
||||
* a boundary byte is taken to be in the previous segment. This is suitable
|
||||
* for deciding which segment to write given a pointer to a record end,
|
||||
* for example. (We can assume xrecoff is not zero, since no valid recptr
|
||||
* can have that.)
|
||||
* for example.
|
||||
*/
|
||||
#define XLByteToSeg(xlrp, logSegNo) \
|
||||
logSegNo = ((uint64) (xlrp).xlogid * XLogSegmentsPerXLogId) + (xlrp).xrecoff / XLogSegSize
|
||||
logSegNo = (xlrp) / XLogSegSize
|
||||
|
||||
#define XLByteToPrevSeg(xlrp, logSegNo) \
|
||||
logSegNo = ((uint64) (xlrp).xlogid * XLogSegmentsPerXLogId) + ((xlrp).xrecoff - 1) / XLogSegSize
|
||||
logSegNo = ((xlrp) - 1) / XLogSegSize
|
||||
|
||||
/*
|
||||
* Is an XLogRecPtr within a particular XLOG segment?
|
||||
|
@ -151,20 +147,15 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
|
|||
* a boundary byte is taken to be in the previous segment.
|
||||
*/
|
||||
#define XLByteInSeg(xlrp, logSegNo) \
|
||||
(((xlrp).xlogid) == (logSegNo) / XLogSegmentsPerXLogId && \
|
||||
((xlrp).xrecoff / XLogSegSize) == (logSegNo) % XLogSegmentsPerXLogId)
|
||||
(((xlrp) / XLogSegSize) == (logSegNo))
|
||||
|
||||
#define XLByteInPrevSeg(xlrp, logSegNo) \
|
||||
(((xlrp).xrecoff == 0) ? \
|
||||
(((xlrp).xlogid - 1) == (logSegNo) / XLogSegmentsPerXLogId && \
|
||||
((uint32) 0xffffffff) / XLogSegSize == (logSegNo) % XLogSegmentsPerXLogId) : \
|
||||
((xlrp).xlogid) == (logSegNo) / XLogSegmentsPerXLogId && \
|
||||
(((xlrp).xrecoff - 1) / XLogSegSize) == (logSegNo) % XLogSegmentsPerXLogId)
|
||||
((((xlrp) - 1) / XLogSegSize) == (logSegNo))
|
||||
|
||||
/* Check if an xrecoff value is in a plausible range */
|
||||
#define XRecOffIsValid(xrecoff) \
|
||||
((xrecoff) % XLOG_BLCKSZ >= SizeOfXLogShortPHD && \
|
||||
(XLOG_BLCKSZ - (xrecoff) % XLOG_BLCKSZ) >= SizeOfXLogRecord)
|
||||
/* Check if an XLogRecPtr value is in a plausible range */
|
||||
#define XRecOffIsValid(xlrp) \
|
||||
((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD && \
|
||||
(XLOG_BLCKSZ - (xlrp) % XLOG_BLCKSZ) >= SizeOfXLogRecord)
|
||||
|
||||
/*
|
||||
* The XLog directory and control file (relative to $PGDATA)
|
||||
|
|
|
@ -17,55 +17,30 @@
|
|||
/*
|
||||
* Pointer to a location in the XLOG. These pointers are 64 bits wide,
|
||||
* because we don't want them ever to overflow.
|
||||
*
|
||||
* NOTE: xrecoff == 0 is used to indicate an invalid pointer. This is OK
|
||||
* because we use page headers in the XLOG, so no XLOG record can start
|
||||
* right at the beginning of a file.
|
||||
*
|
||||
* NOTE: the "log file number" is somewhat misnamed, since the actual files
|
||||
* making up the XLOG are much smaller than 4Gb. Each actual file is an
|
||||
* XLogSegSize-byte "segment" of a logical log file having the indicated
|
||||
* xlogid. The log file number and segment number together identify a
|
||||
* physical XLOG file. Segment number and offset within the physical file
|
||||
* are computed from xrecoff div and mod XLogSegSize.
|
||||
*/
|
||||
typedef struct XLogRecPtr
|
||||
{
|
||||
uint32 xlogid; /* log file #, 0 based */
|
||||
uint32 xrecoff; /* byte offset of location in log file */
|
||||
} XLogRecPtr;
|
||||
|
||||
#define XLogRecPtrIsInvalid(r) ((r).xrecoff == 0)
|
||||
typedef uint64 XLogRecPtr;
|
||||
|
||||
/*
|
||||
* Zero is used indicate an invalid pointer. Bootstrap skips the first possible
|
||||
* WAL segment, initializing the first WAL page at XLOG_SEG_SIZE, so no XLOG
|
||||
* record can begin at zero.
|
||||
*/
|
||||
#define InvalidXLogRecPtr 0
|
||||
#define XLogRecPtrIsInvalid(r) ((r) == InvalidXLogRecPtr)
|
||||
|
||||
/*
|
||||
* Macros for comparing XLogRecPtrs
|
||||
*
|
||||
* Beware of passing expressions with side-effects to these macros,
|
||||
* since the arguments may be evaluated multiple times.
|
||||
*/
|
||||
#define XLByteLT(a, b) \
|
||||
((a).xlogid < (b).xlogid || \
|
||||
((a).xlogid == (b).xlogid && (a).xrecoff < (b).xrecoff))
|
||||
|
||||
#define XLByteLE(a, b) \
|
||||
((a).xlogid < (b).xlogid || \
|
||||
((a).xlogid == (b).xlogid && (a).xrecoff <= (b).xrecoff))
|
||||
|
||||
#define XLByteEQ(a, b) \
|
||||
((a).xlogid == (b).xlogid && (a).xrecoff == (b).xrecoff)
|
||||
#define XLByteLT(a, b) ((a) < (b))
|
||||
#define XLByteLE(a, b) ((a) <= (b))
|
||||
#define XLByteEQ(a, b) ((a) == (b))
|
||||
|
||||
|
||||
/*
|
||||
* Macro for advancing a record pointer by the specified number of bytes.
|
||||
*/
|
||||
#define XLByteAdvance(recptr, nbytes) \
|
||||
do { \
|
||||
uint32 oldxrecoff = (recptr).xrecoff; \
|
||||
(recptr).xrecoff += nbytes; \
|
||||
if ((recptr).xrecoff < oldxrecoff) \
|
||||
(recptr).xlogid += 1; /* xrecoff wrapped around */ \
|
||||
} while (0)
|
||||
(recptr) += nbytes \
|
||||
|
||||
/*
|
||||
* XLogSegNo - physical log file sequence number.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
|
||||
/* Version identifier for this pg_control format */
|
||||
#define PG_CONTROL_VERSION 922
|
||||
#define PG_CONTROL_VERSION 931
|
||||
|
||||
/*
|
||||
* Body of CheckPoint XLOG records. This is declared here because we keep
|
||||
|
|
|
@ -119,10 +119,18 @@ typedef uint16 LocationIndex;
|
|||
* On the high end, we can only support pages up to 32KB because lp_off/lp_len
|
||||
* are 15 bits.
|
||||
*/
|
||||
|
||||
/* for historical reasons, the LSN is stored as two 32-bit values. */
|
||||
typedef struct
|
||||
{
|
||||
uint32 xlogid; /* high bits */
|
||||
uint32 xrecoff; /* low bits */
|
||||
} PageXLogRecPtr;
|
||||
|
||||
typedef struct PageHeaderData
|
||||
{
|
||||
/* XXX LSN is member of *any* block, not only page-organized ones */
|
||||
XLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
|
||||
PageXLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
|
||||
* record for last change to this page */
|
||||
uint16 pd_tli; /* least significant bits of the TimeLineID
|
||||
* containing the LSN */
|
||||
|
@ -314,9 +322,10 @@ typedef PageHeaderData *PageHeader;
|
|||
* Additional macros for access to page headers
|
||||
*/
|
||||
#define PageGetLSN(page) \
|
||||
(((PageHeader) (page))->pd_lsn)
|
||||
((uint64) ((PageHeader) (page))->pd_lsn.xlogid << 32 | ((PageHeader) (page))->pd_lsn.xrecoff)
|
||||
#define PageSetLSN(page, lsn) \
|
||||
(((PageHeader) (page))->pd_lsn = (lsn))
|
||||
(((PageHeader) (page))->pd_lsn.xlogid = (uint32) ((lsn) >> 32), \
|
||||
((PageHeader) (page))->pd_lsn.xrecoff = (uint32) (lsn))
|
||||
|
||||
/* NOTE: only the 16 least significant bits are stored */
|
||||
#define PageGetTLI(page) \
|
||||
|
|
Loading…
Reference in a new issue