diff options
Diffstat (limited to 'src/include/storage/buf_internals.h')
-rw-r--r-- | src/include/storage/buf_internals.h | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 406db6be783..c3417b28ba9 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -92,29 +92,66 @@ typedef struct buftag { Oid spcOid; /* tablespace oid */ Oid dbOid; /* database oid */ - RelFileNumber relNumber; /* relation file number */ - ForkNumber forkNum; /* fork number */ + + /* + * relForkDetails[] stores the fork number in the high 8 bits of the first + * integer; the remaining 56 bits are used to store the relfilenmber. + * Expanding the relfilenumber to a full 64 bits would require widening + * the BufferTag, which is undesirable for performance reasons. We use + * two 32-bit values here rather than a single 64-bit value to avoid + * padding the struct out to a multiple of 8 bytes. + */ + uint32 relForkDetails[2]; BlockNumber blockNum; /* blknum relative to begin of reln */ } BufferTag; +/* High relNumber bits in relForkDetails[0] */ +#define BUFTAG_RELNUM_HIGH_BITS 24 + +/* Low relNumber bits in relForkDetails[1] */ +#define BUFTAG_RELNUM_LOW_BITS 32 + +/* Mask to fetch high bits of relNumber from relForkDetails[0] */ +#define BUFTAG_RELNUM_HIGH_MASK ((1U << BUFTAG_RELNUM_HIGH_BITS) - 1) + +/* Mask to fetch low bits of relNumber from relForkDetails[1] */ +#define BUFTAG_RELNUM_LOW_MASK 0XFFFFFFFF + static inline RelFileNumber BufTagGetRelNumber(const BufferTag *tag) { - return tag->relNumber; + uint64 relnum; + + relnum = ((uint64) tag->relForkDetails[0]) & BUFTAG_RELNUM_HIGH_MASK; + relnum = (relnum << BUFTAG_RELNUM_LOW_BITS) | tag->relForkDetails[1]; + + Assert(relnum <= MAX_RELFILENUMBER); + return (RelFileNumber) relnum; } static inline ForkNumber BufTagGetForkNum(const BufferTag *tag) { - return tag->forkNum; + ForkNumber ret; + + StaticAssertStmt(MAX_FORKNUM <= INT8_MAX, + "MAX_FORKNUM can't be greater than INT8_MAX"); + + ret = (int8) (tag->relForkDetails[0] >> BUFTAG_RELNUM_HIGH_BITS); + return ret; } static inline void BufTagSetRelForkDetails(BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum) { - tag->relNumber = relnumber; - tag->forkNum = forknum; + Assert(relnumber <= MAX_RELFILENUMBER); + Assert(forknum <= MAX_FORKNUM); + + tag->relForkDetails[0] = (relnumber >> BUFTAG_RELNUM_LOW_BITS) & + BUFTAG_RELNUM_HIGH_MASK; + tag->relForkDetails[0] |= (forknum << BUFTAG_RELNUM_HIGH_BITS); + tag->relForkDetails[1] = relnumber & BUFTAG_RELNUM_LOW_MASK; } static inline RelFileLocator @@ -153,9 +190,9 @@ BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2) { return (tag1->spcOid == tag2->spcOid) && (tag1->dbOid == tag2->dbOid) && - (tag1->relNumber == tag2->relNumber) && - (tag1->blockNum == tag2->blockNum) && - (tag1->forkNum == tag2->forkNum); + (tag1->relForkDetails[0] == tag2->relForkDetails[0]) && + (tag1->relForkDetails[1] == tag2->relForkDetails[1]) && + (tag1->blockNum == tag2->blockNum); } static inline bool |