diff options
| author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-06-24 18:51:37 +0300 |
|---|---|---|
| committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-06-24 19:19:45 +0300 |
| commit | 0ab9d1c4b31622e9176472b4276f3e9831e3d6ba (patch) | |
| tree | b8e9e5337338ba3010e00af50e1a33adb906a212 /src/include | |
| parent | 061e7efb1b4c5b8a5d02122b7780531b8d5bf23d (diff) | |
| download | postgresql-0ab9d1c4b31622e9176472b4276f3e9831e3d6ba.tar.gz | |
Replace XLogRecPtr struct with a 64-bit integer.
This simplifies code that needs to do arithmetic on XLogRecPtrs.
To avoid changing on-disk format of data pages, the LSN on data pages is
still stored in the old format. That should keep pg_upgrade happy. However,
we have XLogRecPtrs embedded in the control file, and in the structs that
are sent over the replication protocol, so this changes breaks compatibility
of pg_basebackup and server. I didn't do anything about this in this patch,
per discussion on -hackers, the right thing to do would to be to change the
replication protocol to be architecture-independent, so that you could use
a newer version of pg_receivexlog, for example, against an older server
version.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/transam.h | 4 | ||||
| -rw-r--r-- | src/include/access/xlog_internal.h | 37 | ||||
| -rw-r--r-- | src/include/access/xlogdefs.h | 49 | ||||
| -rw-r--r-- | src/include/catalog/pg_control.h | 2 | ||||
| -rw-r--r-- | src/include/storage/bufpage.h | 15 |
5 files changed, 39 insertions, 68 deletions
diff --git a/src/include/access/transam.h b/src/include/access/transam.h index 937386575b..228f6a12c3 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -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 */ diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h index d6e4bc5d7f..4ad4d13699 100644 --- a/src/include/access/xlog_internal.h +++ b/src/include/access/xlog_internal.h @@ -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) diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h index 603854884f..153d0de22a 100644 --- a/src/include/access/xlogdefs.h +++ b/src/include/access/xlogdefs.h @@ -17,55 +17,30 @@ /* * Pointer to a location in the XLOG. These pointers are 64 bits wide, * because we don't want them ever to overflow. - * - * NOTE: xrecoff == 0 is used to indicate an invalid pointer. This is OK - * because we use page headers in the XLOG, so no XLOG record can start - * right at the beginning of a file. - * - * NOTE: the "log file number" is somewhat misnamed, since the actual files - * making up the XLOG are much smaller than 4Gb. Each actual file is an - * XLogSegSize-byte "segment" of a logical log file having the indicated - * xlogid. The log file number and segment number together identify a - * physical XLOG file. Segment number and offset within the physical file - * are computed from xrecoff div and mod XLogSegSize. */ -typedef struct XLogRecPtr -{ - uint32 xlogid; /* log file #, 0 based */ - uint32 xrecoff; /* byte offset of location in log file */ -} XLogRecPtr; - -#define XLogRecPtrIsInvalid(r) ((r).xrecoff == 0) +typedef uint64 XLogRecPtr; +/* + * Zero is used indicate an invalid pointer. Bootstrap skips the first possible + * WAL segment, initializing the first WAL page at XLOG_SEG_SIZE, so no XLOG + * record can begin at zero. + */ +#define InvalidXLogRecPtr 0 +#define XLogRecPtrIsInvalid(r) ((r) == InvalidXLogRecPtr) /* * Macros for comparing XLogRecPtrs - * - * Beware of passing expressions with side-effects to these macros, - * since the arguments may be evaluated multiple times. */ -#define XLByteLT(a, b) \ - ((a).xlogid < (b).xlogid || \ - ((a).xlogid == (b).xlogid && (a).xrecoff < (b).xrecoff)) - -#define XLByteLE(a, b) \ - ((a).xlogid < (b).xlogid || \ - ((a).xlogid == (b).xlogid && (a).xrecoff <= (b).xrecoff)) - -#define XLByteEQ(a, b) \ - ((a).xlogid == (b).xlogid && (a).xrecoff == (b).xrecoff) +#define XLByteLT(a, b) ((a) < (b)) +#define XLByteLE(a, b) ((a) <= (b)) +#define XLByteEQ(a, b) ((a) == (b)) /* * Macro for advancing a record pointer by the specified number of bytes. */ #define XLByteAdvance(recptr, nbytes) \ - do { \ - uint32 oldxrecoff = (recptr).xrecoff; \ - (recptr).xrecoff += nbytes; \ - if ((recptr).xrecoff < oldxrecoff) \ - (recptr).xlogid += 1; /* xrecoff wrapped around */ \ - } while (0) + (recptr) += nbytes \ /* * XLogSegNo - physical log file sequence number. diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h index 5cff39608b..c9ee80531c 100644 --- a/src/include/catalog/pg_control.h +++ b/src/include/catalog/pg_control.h @@ -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 diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index 1ab64e021d..fc3a69b678 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -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) \ |
