]> granicus.if.org Git - postgresql/commitdiff
Replace XLogRecPtr struct with a 64-bit integer.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 24 Jun 2012 15:51:37 +0000 (18:51 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 24 Jun 2012 16:19:45 +0000 (19:19 +0300)
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.

28 files changed:
contrib/pageinspect/rawpage.c
src/backend/access/gist/gist.c
src/backend/access/gist/gistutil.c
src/backend/access/transam/transam.c
src/backend/access/transam/twophase.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/access/transam/xlogfuncs.c
src/backend/postmaster/checkpointer.c
src/backend/replication/basebackup.c
src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
src/backend/replication/repl_scanner.l
src/backend/replication/syncrep.c
src/backend/replication/walreceiver.c
src/backend/replication/walreceiverfuncs.c
src/backend/replication/walsender.c
src/backend/storage/ipc/standby.c
src/backend/storage/lmgr/proc.c
src/bin/pg_basebackup/pg_basebackup.c
src/bin/pg_basebackup/pg_receivexlog.c
src/bin/pg_basebackup/receivelog.c
src/bin/pg_controldata/pg_controldata.c
src/bin/pg_resetxlog/pg_resetxlog.c
src/include/access/transam.h
src/include/access/xlog_internal.h
src/include/access/xlogdefs.h
src/include/catalog/pg_control.h
src/include/storage/bufpage.h

index f51a4e31f51ae5bd00f31dc4bd3daa5015d5917c..e8a79401adc3a7cc35e84b67777418508ee395d3 100644 (file)
@@ -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));
index 783590ea55e59134bbd22cbf17bd4712e4e543a4..64ad2d749b066ad9c57ccf43be143798106f8444 100644 (file)
@@ -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;
index 8039b5d569c27fd67678f9b26e961c24c1365c9a..df1e2e396f268e4b09e898c0b614a1d0cb3e7dfa 100644 (file)
@@ -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;
 }
index a7214cf34dedf7ffbb01f50f4dedbb8d50c8a1cd..ff9dd4beeada65fb62cabe1fba5270db13ae6fee 100644 (file)
@@ -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
index b94fae3740251426b80dff346fc03424e7e6a76f..7fbf605761b96544b81b10ba2bcc7ce08bf899e2 100644 (file)
@@ -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;
index 8e4a45568b3ae2b71da85861f5e8120aac0c5065..4ba13e18abb22d5aa0d7afb90c645f5e24cfc6d7 100644 (file)
@@ -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
index a144fbb1a2ca821a452d6366655cdd03e10daabc..f0a89ac29a2e10fc07f1592bb2270f5e64e74179 100644 (file)
@@ -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)
        {
index bbb87d4d5cd847ed0f025b55ae3d2f248d42ecfb..6a446e96889f0fa72d0f2e3209585eaa19f9cd4a 100644 (file)
@@ -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.
index 7e5db863daf254f0431d6b1bccfef21959b78af9..417e3bb0d1b0c90632aafa5fbec351ab21f7e5a0 100644 (file)
@@ -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)
                {
index 14c42b46c23b2ea4ed282ad7fb9402e33a730724..4aaa9e3d0886013165131f3e4b090d75df4fe0f0 100644 (file)
@@ -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 */
index 979b66b300a8e1e471df176cab756444f66fa08f..bfaebeae84286908ff2dd0df240943ec70e084d7 100644 (file)
@@ -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)
        {
index 9d4edcfc7a524cf3add7dde99f41d65e494e97df..51f381da000803a71a5a95cfc109a3d17e70356c 100644 (file)
@@ -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;
                                }
 
index a3319642c628e99aef7c5cf55b40d2ddb907bbe5..0bb4145cb0c4cc6ec5c35dc49af1d947431a5be9 100644 (file)
@@ -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]),
index b3ba7089dfb39927744437759e8989bb84008d8f..d0e92060f1173a6a7a6bddaf584dc4eaab636b05 100644 (file)
@@ -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';
index 876196f9da397fe578a5b1819f6d34ff9d563b3f..b31e964fecd6276567ce8065810b17ded89d51d9 100644 (file)
@@ -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;
index 2c04df08ed1874499543bdb410b8d45dfa357774..0541c249988697078a4c7d73bca4d9c4bff8cf87 100644 (file)
@@ -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]);
index 8863a5c9a7f57397b4c7bccddf91593e1d2dacfc..995b68aae553f6cbbc1dbfc0a05ddeb4404bfc7c 100644 (file)
@@ -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);
index 327f43bb352925e78bd49b3830973b7f487870e7..21598d3c18635acee2728bd54910732b34904952 100644 (file)
@@ -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));
 
index bc67a3cb4d4ae21151a6025567a37eba8f99d8c6..a66769871ec5eb08f98e5304ed7f6a5d4ba19320 100644 (file)
@@ -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", &param->startptr.xlogid, &param->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 */
index 4b109f4b96fe7cb92192e3585320d6453e5cf945..dbc6ecf431de12bb8401cf179969483662dfe965 100644 (file)
@@ -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,
index 8c6755caa981c01d8be5812a4b343af508f9d621..064315f8dbc7c7833fd8a1b1251bae271e02934f 100644 (file)
@@ -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() */
index 38c263c08be4d74d28170a5f0d1b1d29d869bdb2..298f836504f55445bf1231627354dce96c7af1c8 100644 (file)
@@ -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"),
index 45d9aa3d234584fadedf67121aba4983846d33a5..3500c4cf1d49a627a3585b193a872c3f16effcec 100644 (file)
@@ -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);
index 937386575b69354e756e4a93579dfea0c468ee50..228f6a12c36b5b565e66ef8d0ebd376b0e67eaad 100644 (file)
@@ -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
  */
index d6e4bc5d7fd5a35a9a5c78e533ab73edcc400838..4ad4d136999da1151abdf632adfcfc075f3b5091 100644 (file)
@@ -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)
-
-/* Check if an xrecoff value is in a plausible range */
-#define XRecOffIsValid(xrecoff) \
-               ((xrecoff) % XLOG_BLCKSZ >= SizeOfXLogShortPHD && \
-               (XLOG_BLCKSZ - (xrecoff) % XLOG_BLCKSZ) >= SizeOfXLogRecord)
+       ((((xlrp) - 1) / XLogSegSize) == (logSegNo))
+
+/* 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)
index 603854884f0eee143001f3c0c195020f19e1de30..153d0de22a9cb7f4f25227ae75ce43358847efe0 100644 (file)
 /*
  * 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.
index 5cff39608bae71caa16e6f99039baa60c7491737..c9ee80531c3b122392f5a5d210ed8e4fdce055ee 100644 (file)
@@ -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
index 1ab64e021d5e762e0a25eac892560726d692f638..fc3a69b678fd12d0c73dfa101f3b02653952c9e6 100644 (file)
@@ -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) \