Replace XLogRecPtr struct with a 64-bit integer.
authorHeikki Linnakangas
Sun, 24 Jun 2012 15:51:37 +0000 (18:51 +0300)
committerHeikki Linnakangas
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, ¶m->startptr.xrecoff) != 2)
+   if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
    {
        fprintf(stderr, _("%s: invalid format of xlog location: %s\n"),
                progname, startpos);
        disconnect_and_exit(1);
    }
+   param->startptr = ((uint64) hi) << 32 | lo;
    /* Round off to even segment position */
-   param->startptr.xrecoff -= param->startptr.xrecoff % XLOG_SEG_SIZE;
+   param->startptr -= param->startptr % XLOG_SEG_SIZE;
 
 #ifndef WIN32
    /* Create our background pipe */
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) \