#ifndef BUFPAGE_H
#define BUFPAGE_H
#include "access/xlogdefs.h"
#include "storage/block.h"
#include "storage/item.h"
#include "storage/off.h"
typedef Pointer Page;
typedef uint16 LocationIndex;
typedef struct
{
uint32 xlogid;
uint32 xrecoff;
} PageXLogRecPtr;
static inline XLogRecPtr
PageXLogRecPtrGet(PageXLogRecPtr val)
{
return (uint64) val.xlogid << 32 | val.xrecoff;
}
#define PageXLogRecPtrSet(ptr, lsn) \
((ptr).xlogid = (uint32) ((lsn) >> 32), (ptr).xrecoff = (uint32) (lsn))
typedef struct PageHeaderData
{
PageXLogRecPtr pd_lsn;
uint16 pd_checksum;
uint16 pd_flags;
LocationIndex pd_lower;
LocationIndex pd_upper;
LocationIndex pd_special;
uint16 pd_pagesize_version;
TransactionId pd_prune_xid;
ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER];
} PageHeaderData;
typedef PageHeaderData *PageHeader;
#define PD_HAS_FREE_LINES 0x0001
#define PD_PAGE_FULL 0x0002
#define PD_ALL_VISIBLE 0x0004
#define PD_VALID_FLAG_BITS 0x0007
#define PG_PAGE_LAYOUT_VERSION 4
#define PG_DATA_CHECKSUM_VERSION 1
#define SizeOfPageHeaderData (offsetof(PageHeaderData, pd_linp))
static inline bool
PageIsEmpty(Page page)
{
return ((PageHeader) page)->pd_lower <= SizeOfPageHeaderData;
}
static inline bool
PageIsNew(Page page)
{
return ((PageHeader) page)->pd_upper == 0;
}
static inline ItemId
PageGetItemId(Page page, OffsetNumber offsetNumber)
{
return &((PageHeader) page)->pd_linp[offsetNumber - 1];
}
static inline char *
PageGetContents(Page page)
{
return (char *) page + MAXALIGN(SizeOfPageHeaderData);
}
static inline Size
PageGetPageSize(Page page)
{
return (Size) (((PageHeader) page)->pd_pagesize_version & (uint16) 0xFF00);
}
static inline uint8
PageGetPageLayoutVersion(Page page)
{
return (((PageHeader) page)->pd_pagesize_version & 0x00FF);
}
static inline void
PageSetPageSizeAndVersion(Page page, Size size, uint8 version)
{
Assert((size & 0xFF00) == size);
Assert((version & 0x00FF) == version);
((PageHeader) page)->pd_pagesize_version = size | version;
}
static inline uint16
PageGetSpecialSize(Page page)
{
return (PageGetPageSize(page) - ((PageHeader) page)->pd_special);
}
static inline void
PageValidateSpecialPointer(Page page)
{
Assert(page);
Assert(((PageHeader) page)->pd_special <= BLCKSZ);
Assert(((PageHeader) page)->pd_special >= SizeOfPageHeaderData);
}
static inline char *
PageGetSpecialPointer(Page page)
{
PageValidateSpecialPointer(page);
return (char *) page + ((PageHeader) page)->pd_special;
}
static inline Item
PageGetItem(Page page, ItemId itemId)
{
Assert(page);
Assert(ItemIdHasStorage(itemId));
return (Item) (((char *) page) + ItemIdGetOffset(itemId));
}
static inline OffsetNumber
PageGetMaxOffsetNumber(Page page)
{
PageHeader pageheader = (PageHeader) page;
if (pageheader->pd_lower <= SizeOfPageHeaderData)
return 0;
else
return (pageheader->pd_lower - SizeOfPageHeaderData) / sizeof(ItemIdData);
}
static inline XLogRecPtr
PageGetLSN(Page page)
{
return PageXLogRecPtrGet(((PageHeader) page)->pd_lsn);
}
static inline void
PageSetLSN(Page page, XLogRecPtr lsn)
{
PageXLogRecPtrSet(((PageHeader) page)->pd_lsn, lsn);
}
static inline bool
PageHasFreeLinePointers(Page page)
{
return ((PageHeader) page)->pd_flags & PD_HAS_FREE_LINES;
}
static inline void
PageSetHasFreeLinePointers(Page page)
{
((PageHeader) page)->pd_flags |= PD_HAS_FREE_LINES;
}
static inline void
PageClearHasFreeLinePointers(Page page)
{
((PageHeader) page)->pd_flags &= ~PD_HAS_FREE_LINES;
}
static inline bool
PageIsFull(Page page)
{
return ((PageHeader) page)->pd_flags & PD_PAGE_FULL;
}
static inline void
PageSetFull(Page page)
{
((PageHeader) page)->pd_flags |= PD_PAGE_FULL;
}
static inline void
PageClearFull(Page page)
{
((PageHeader) page)->pd_flags &= ~PD_PAGE_FULL;
}
static inline bool
PageIsAllVisible(Page page)
{
return ((PageHeader) page)->pd_flags & PD_ALL_VISIBLE;
}
static inline void
PageSetAllVisible(Page page)
{
((PageHeader) page)->pd_flags |= PD_ALL_VISIBLE;
}
static inline void
PageClearAllVisible(Page page)
{
((PageHeader) page)->pd_flags &= ~PD_ALL_VISIBLE;
}
#define PageSetPrunable(page, xid) \
do { \
Assert(TransactionIdIsNormal(xid)); \
if (!TransactionIdIsValid(((PageHeader) (page))->pd_prune_xid) || \
TransactionIdPrecedes(xid, ((PageHeader) (page))->pd_prune_xid)) \
((PageHeader) (page))->pd_prune_xid = (xid); \
} while (0)
#define PageClearPrunable(page) \
(((PageHeader) (page))->pd_prune_xid = InvalidTransactionId)
#define PAI_OVERWRITE (1 << 0)
#define PAI_IS_HEAP (1 << 1)
#define PIV_LOG_WARNING (1 << 0)
#define PIV_REPORT_STAT (1 << 1)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap) \
PageAddItemExtended(page, item, size, offsetNumber, \
((overwrite) ? PAI_OVERWRITE : 0) | \
((is_heap) ? PAI_IS_HEAP : 0))
#define PageIsVerified(page, blkno) \
PageIsVerifiedExtended(page, blkno, \
PIV_LOG_WARNING | PIV_REPORT_STAT)
StaticAssertDecl(BLCKSZ == ((BLCKSZ / sizeof(size_t)) * sizeof(size_t)),
"BLCKSZ has to be a multiple of sizeof(size_t)");
extern void PageInit(Page page, Size pageSize, Size specialSize);
extern bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags);
extern OffsetNumber PageAddItemExtended(Page page, Item item, Size size,
OffsetNumber offsetNumber, int flags);
extern Page PageGetTempPage(Page page);
extern Page PageGetTempPageCopy(Page page);
extern Page PageGetTempPageCopySpecial(Page page);
extern void PageRestoreTempPage(Page tempPage, Page oldPage);
extern void PageRepairFragmentation(Page page);
extern void PageTruncateLinePointerArray(Page page);
extern Size PageGetFreeSpace(Page page);
extern Size PageGetFreeSpaceForMultipleTuples(Page page, int ntups);
extern Size PageGetExactFreeSpace(Page page);
extern Size PageGetHeapFreeSpace(Page page);
extern void PageIndexTupleDelete(Page page, OffsetNumber offnum);
extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems);
extern void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum);
extern bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum,
Item newtup, Size newsize);
extern char *PageSetChecksumCopy(Page page, BlockNumber blkno);
extern void PageSetChecksumInplace(Page page, BlockNumber blkno);
#endif