Ai
443 Star 1.5K Fork 1.8K

openGauss/openGauss-server

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
knl_upage.h 15.74 KB
一键复制 编辑 原始数据 按行查看 历史
yaoxin 提交于 2024-12-12 20:12 +08:00 . fix spaces expansion of uheap
/* -------------------------------------------------------------------------
*
* knl_upage.h
* the page format of inplace update engine.
*
* Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/include/access/ustore/knl_upage.h
* -------------------------------------------------------------------------
*/
#ifndef KNL_UPAGE_H
#define KNL_UPAGE_H
#include "storage/buf/bufpage.h"
#include "access/genam.h"
#include "access/ustore/knl_utype.h"
#include "access/ustore/knl_utuple.h"
#include "access/ustore/knl_uverify.h"
#include "utils/rel.h"
#define TD_SLOT_INCREMENT_SIZE 2
#define TD_THRESHOLD_FOR_PAGE_SWITCH 32
#define FORCE_EXTEND_THRESHOLD 3
#define DML_MAX_RETRY_TIMES 100000
#define UHEAP_HAS_FREE_LINES 0x0001 /* are there any unused line pointers? */
#define UHEAP_PAGE_FULL 0x0002 /* not enough free space for new \
* tuple? */
#define UHP_ALL_VISIBLE 0x0004 /* all tuples on page are visible to \
* everyone */
#define UHEAP_VALID_FLAG_BITS 0xFFFF /* OR of all valid flag bits */
#define XLOG_LSN_HIGH_OFF 32
#define UPageHasFreeLinePointers(_page) (((UHeapPageHeaderData *)(_page))->pd_flags & UHEAP_HAS_FREE_LINES)
#define UPageSetHasFreeLinePointers(_page) (((UHeapPageHeaderData *)(_page))->pd_flags |= UHEAP_HAS_FREE_LINES)
#define UPageClearHasFreeLinePointers(_page) (((UHeapPageHeaderData *)(_page))->pd_flags &= ~UHEAP_HAS_FREE_LINES)
#define UPageIsFull(_page) (((UHeapPageHeaderData *)(_page))->pd_flags & UHEAP_PAGE_FULL)
#define UPageSetFull(_page) (((UHeapPageHeaderData *)(_page))->pd_flags |= UHEAP_PAGE_FULL)
#define UPageClearFull(_page) (((UHeapPageHeaderData *)(_page))->pd_flags &= ~UHEAP_PAGE_FULL)
#define SizeOfUHeapPageHeaderData (sizeof(UHeapPageHeaderData))
#define SizeOfUHeapTDData(_uphdr) ((_uphdr)->td_count * sizeof(TD))
#define UPageGetRowPtrOffset(_page) (SizeOfUHeapPageHeaderData + SizeOfUHeapTDData((UHeapPageHeaderData *)_page))
#define UPageGetRowPtr(_upage, _offsetNumber) (UPageGenerateRowPtr(_upage, _offsetNumber))
#define UPageGenerateRowPtr(_upage, _offsetNumber) \
((RowPtr *)(((char *)_upage) + SizeOfUHeapPageHeaderData + SizeOfUHeapTDData((UHeapPageHeaderData *)_upage) + \
((_offsetNumber - 1) * sizeof(RowPtr))))
#define SetNormalRowPointer(_rowptr, _off, _size) \
((_rowptr)->flags = RP_NORMAL, (_rowptr)->offset = (_off), (_rowptr)->len = (_size))
#define UPageGetRowData(_upage, _rowptr) \
(AssertMacro(PageIsValid(_upage)), AssertMacro(RowPtrHasStorage(_rowptr)), \
(Item)(((char *)(_upage)) + RowPtrGetOffset(_rowptr)))
#define PageGetTDPointer(_page) ((char *)((char *)(_page) + SizeOfUHeapPageHeaderData))
#define PageGetTDPointerBySlot(_page, _slot) (PageGetTDPointer(_page) + (_slot) * sizeof(TD))
#define GetTDCount(_uphdr) ((_uphdr)->td_count)
#define UPageGetTDSlotCount(_page) ((UHeapPageHeaderData *)(_page))->td_count
#define UPageIsPrunable(_page) \
(TransactionIdIsValid(((UHeapPageHeaderData *)(_page))->pd_prune_xid) && \
!TransactionIdIsInProgress(((UHeapPageHeaderData *)(_page))->pd_prune_xid))
#define UPageIsPrunableWithXminHorizon(_page, _oldestxmin) \
(AssertMacro(TransactionIdIsNormal(_oldestxmin)), \
TransactionIdIsValid(((UHeapPageHeaderData *)(_page))->pd_prune_xid) && \
TransactionIdPrecedes(((UHeapPageHeaderData *)(_page))->pd_prune_xid, _oldestxmin))
#define UPageSetPrunable(_page, _xid) \
do { \
Assert(TransactionIdIsNormal(_xid)); \
if (!TransactionIdIsValid(((UHeapPageHeaderData *)(_page))->pd_prune_xid) || \
TransactionIdPrecedes(_xid, ((UHeapPageHeaderData *)(_page))->pd_prune_xid)) \
((UHeapPageHeaderData *)(_page))->pd_prune_xid = (_xid); \
} while (0)
#define UPageClearPrunable(_page) (((UHeapPageHeaderData *)(_page))->pd_prune_xid = InvalidTransactionId)
#define LimitRetryTimes(retryTimes) \
do { \
if ((retryTimes) > DML_MAX_RETRY_TIMES) { \
elog(ERROR, "Transaction aborted due to too many retries."); \
} \
} while (0)
/*
* RowPtr "flags" has these possible states. An UNUSED row pointer is available
* for immediate re-use, the other states are not.
*/
#define RP_UNUSED 0 /* unused (should always have len=0) */
#define RP_NORMAL 1 /* used (should always have len>0) */
#define RP_REDIRECT 2 /* HOT redirect (should have len=0) */
#define RP_DEAD 3 /* dead, may or may not have storage */
/*
* Flags used in UHeap. These flags are used in a row pointer of a deleted
* row that has no actual storage. These help in fetching the tuple from
* undo when required.
*/
#define ROWPTR_DELETED 0x0001 /* Row is deleted */
#define ROWPTR_XACT_INVALID 0x0002 /* TD slot on tuple got reused */
#define VISIBILTY_MASK 0x007F /* 7 bits (1..7) for visibility mask */
#define XACT_SLOT 0x7F80 /* 8 bits (8..15) of offset for transaction \
* slot */
#define XACT_SLOT_MASK 0x0007 /* 7 - mask to retrieve transaction slot */
/*
* RowPtrIsUsed
* True iff row pointer is in use.
*/
#define RowPtrIsUsed(_rowptr) ((_rowptr)->flags != RP_UNUSED)
#define RowPtrHasStorage(_rowptr) ((_rowptr)->len > 0)
#define RowPtrIsNormal(_rowptr) ((_rowptr)->flags == RP_NORMAL)
#define RowPtrGetLen(_rowptr) ((_rowptr)->len)
#define RowPtrGetOffset(_rowptr) ((_rowptr)->offset)
/*
* RowPtrSetUnused
* Set the row pointer to be UNUSED, with no storage.
* Beware of multiple evaluations of itemId!
*/
#define RowPtrSetUnused(_rowptr) ((_rowptr)->flags = RP_UNUSED, (_rowptr)->offset = 0, (_rowptr)->len = 0)
#define RowPtrSetDead(rowptr) ((rowptr)->flags = RP_DEAD, (rowptr)->offset = 0, (rowptr)->len = 0)
#define RowPtrSetDeleted(_itemId, _td_slot, _vis_info) \
((_itemId)->flags = RP_REDIRECT, (_itemId)->offset = ((_itemId)->offset & ~VISIBILTY_MASK) | (_vis_info), \
(_itemId)->offset = ((_itemId)->offset & ~XACT_SLOT) | (_td_slot) << XACT_SLOT_MASK, (_itemId)->len = 0)
/*
* ItemIdChangeLen
* Change the length of itemid.
*/
#define RowPtrChangeLen(_rowptr, _length) ((_rowptr)->len = (_length))
/*
* RowPtrIsDead
* True iff row pointer is in state DEAD.
*/
#define RowPtrIsDead(_rowptr) ((_rowptr)->flags == RP_DEAD)
/*
* RowPtrIsDeleted
* True iff row pointer is in state REDIRECT.
*/
#define RowPtrIsDeleted(_rowptr) ((_rowptr)->flags == RP_REDIRECT)
/*
* RowPtrGetVisibilityInfo
* In a REDIRECT pointer, offset field contains the visibility information in
* least significant 7 bits.
*/
#define RowPtrGetVisibilityInfo(_rowptr) ((_rowptr)->offset & VISIBILTY_MASK)
#define RowPtrSetInvalidXact(_rowptr) ((_rowptr)->offset = ((_rowptr)->offset & ~VISIBILTY_MASK) | ROWPTR_XACT_INVALID)
#define RowPtrResetInvalidXact(_rowptr) \
((_rowptr)->offset = ((_rowptr)->offset & ~VISIBILTY_MASK) & ~(ROWPTR_XACT_INVALID))
/*
* RowPtrGetTDSlot
* In a REDIRECT pointer, offset contains the TD slot information in
* most significant 8 bits.
*/
#define RowPtrGetTDSlot(_rowptr) (((_rowptr)->offset & XACT_SLOT) >> XACT_SLOT_MASK)
/*
* MaxUHeapTupFixedSize - Fixed size for tuple, this is computed based
* on data alignment.
*/
#define MaxUHeapTupFixedSize (SizeOfUHeapDiskTupleData + sizeof(ItemIdData))
/* MaxUHeapPageFixedSpace - Maximum fixed size for page */
#define MaxUHeapPageFixedSpace(relation) \
(BLCKSZ - SizeOfUHeapPageHeaderData - (RelationGetInitTd(relation) * sizeof(TD)) - UHEAP_SPECIAL_SIZE)
#define MaxPossibleUHeapPageFixedSpace (BLCKSZ - SizeOfUHeapPageHeaderData - UHEAP_SPECIAL_SIZE)
#define MaxUHeapToastPageFixedSpace \
(BLCKSZ - SizeOfUHeapPageHeaderData - (UHEAP_DEFAULT_TOAST_TD_COUNT * sizeof(TD)) - UHEAP_SPECIAL_SIZE)
/*
* MaxUHeapTuplesPerPage is an upper bound on the number of tuples that can
* fit on one uheap page.
*/
#define MaxUHeapTuplesPerPage(relation) ((int)((MaxUHeapPageFixedSpace(relation)) / (MaxUHeapTupFixedSize)))
#define MaxPossibleUHeapTuplesPerPage ((int)((MaxPossibleUHeapPageFixedSpace) / (MaxUHeapTupFixedSize)))
#define CalculatedMaxUHeapTuplesPerPage(tdSlots) \
((int)((BLCKSZ - SizeOfUHeapPageHeaderData - (tdSlots * sizeof(TD)) - UHEAP_SPECIAL_SIZE) \
/ (MaxUHeapTupFixedSize)))
#define UPageGetPruneXID(_page) ((UHeapPageHeaderData)(_page))->pd_prune_xid
#define UPagePrintErrorInfo(_page, _msg) \
do { \
UHeapPageHeaderData *pageHeader = (UHeapPageHeaderData *)_page; \
elog(PANIC, \
"%s, UPageHeaderInfo: pd_lsn:%X/%X, pd_checksum:%u, " \
"pd_flags:%u, pd_lower:%u, " \
"pd_upper:%u, pd_special:%u, pd_pagesize_version:%u, potential_freespace:%u, td_count:%u, " \
"pd_prune_xid:%lu, pd_xid_base:%lu, pd_multi_base:%lu", \
_msg, pageHeader->pd_lsn.xlogid, \
(uint32)(((uint64)pageHeader->pd_lsn.xlogid << XLOG_LSN_HIGH_OFF) | pageHeader->pd_lsn.xrecoff), \
pageHeader->pd_checksum, pageHeader->pd_flags, pageHeader->pd_lower, pageHeader->pd_upper, \
pageHeader->pd_special, pageHeader->pd_pagesize_version, pageHeader->potential_freespace, \
pageHeader->td_count, pageHeader->pd_prune_xid, pageHeader->pd_xid_base, pageHeader->pd_multi_base); \
} while (0)
const uint8 UHEAP_DEFAULT_TOAST_TD_COUNT = 4;
const uint8 UHEAP_MAX_ATTR_PAD = 3;
/*
* the disk page format of inplace table
*
* +---------------------+----------------------------+
* | UHeapPageHeaderData | TD1 TD2 TD3 ...TDN |
* +-----------+----+---------------------------------+
* | RowPtr1 RowPtr2 RowPtr3... RowPtrN |
* +-----------+--------------------------------------+
* | ^ pd_lower |
* | |
* | v pd_upper |
* +-------------+------------------------------------+
* | | rowN ... |
* +-------------+------------------+-----------------+
* | ... row3 row2 row1 | "special space" |
* +--------------------------------+-----------------+
* ^ special
*/
typedef struct RowPtr {
unsigned offset : 15, /* offset to row (from start of page) */
flags : 2, /* state of row pointer */
len : 15; /* byte length of row */
} RowPtr;
typedef enum UPageType {
UPAGE_HEAP = 0,
UPAGE_INDEX,
UPAGE_TOAST
} UPageType;
typedef struct UHeapPageHeaderData {
PageXLogRecPtr pd_lsn;
uint16 pd_checksum;
uint16 pd_flags; /* Various page attribute flags e.g. free rowptrs */
uint16 pd_lower; /* Start of the free space between row pointers and row data */
uint16 pd_upper;
uint16 pd_special; /* Pointer to AM-specific per-page data */
uint16 pd_pagesize_version; /* Page version identifier */
uint16 potential_freespace; /* Potential space from deleted and updated tuples */
uint16 td_count; /* Number of TD entries on the page */
TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */
TransactionId pd_xid_base;
TransactionId pd_multi_base;
uint32 reserved;
} UHeapPageHeaderData;
typedef struct UHeapPageTDData {
TD td_info[1];
} UHeapPageTDData;
typedef UHeapPageHeaderData* UHeapPageHeader;
inline bool UPageIsEmpty(UHeapPageHeaderData *phdr)
{
uint16 td_count = phdr->td_count;
uint16 start = (uint16)SizeOfUHeapPageHeaderData + (td_count * sizeof(TD));
return phdr->pd_lower <= start;
}
/*
* Given a page, it stores contiguous ranges of free offsets that can be
* used/reused in the same page. This is used in UHeapMultiInsert to decide
* the number of undo records needs to be prepared before entering into critical
* section.
*/
typedef struct UHeapFreeOffsetRanges {
OffsetNumber startOffset[MaxOffsetNumber];
OffsetNumber endOffset[MaxOffsetNumber];
int nranges;
} UHeapFreeOffsetRanges;
typedef struct UHeapBufferPage {
Buffer buffer;
Page page;
} UHeapBufferPage;
typedef struct {
uint16 start;
uint16 end;
uint16 offset;
} RpSortData;
typedef RpSortData* RpSort;
template<UPageType pagetype>
void UPageInit(Page page, Size pageSize, Size specialSize, uint8 tdSlots = UHEAP_DEFAULT_TD);
template<> void UPageInit<UPageType::UPAGE_HEAP>(Page page, Size page_size, Size special_size, uint8 tdSlots);
template<> void UPageInit<UPageType::UPAGE_TOAST>(Page page, Size page_size, Size special_size, uint8 tdSlots);
OffsetNumber UPageAddItem(Relation relation, UHeapBufferPage *bufpage, Item item, Size size,
OffsetNumber offsetNumber, bool overwrite);
UHeapTuple UHeapGetTuple(Relation relation, Buffer buffer, OffsetNumber offnum, UHeapTuple freebuf = NULL);
UHeapTuple UHeapGetTuplePartial(Relation relation, Buffer buffer, OffsetNumber offnum, AttrNumber lastVar = -1,
bool *boolArr = NULL);
Size PageGetUHeapFreeSpace(Page page);
Size PageGetExactUHeapFreeSpace(Page page);
extern UHeapFreeOffsetRanges *UHeapGetUsableOffsetRanges(Buffer buffer, UHeapTuple *tuples, int ntuples,
Size saveFreeSpace);
extern bool VerifyPageHeader(Page page);
extern void FastVerifyUTuple(UHeapDiskTuple diskTup, Buffer buffer);
void UHeapRecordPotentialFreeSpace(Buffer buffer, int delta);
/*
* UPageGetMaxOffsetNumber
* Returns the maximum offset number used by the given page.
* Since offset numbers are 1-based, this is also the number
* of items on the page.
*
* NOTE: if the page is not initialized (pd_lower == 0), we must
* return zero to ensure sane behavior.
*/
inline OffsetNumber UHeapPageGetMaxOffsetNumber(char *upage)
{
OffsetNumber maxoff = InvalidOffsetNumber;
UHeapPageHeaderData *upghdr = (UHeapPageHeaderData *)upage;
if (upghdr->pd_lower <= SizeOfUHeapPageHeaderData)
maxoff = 0;
else
maxoff = (upghdr->pd_lower - (SizeOfUHeapPageHeaderData + SizeOfUHeapTDData(upghdr))) / sizeof(RowPtr);
return maxoff;
}
#define USTORE_VERIFY_UPAGE_HEADER 0x01
#define USTORE_VERIFY_UPAGE_TUPLE 0x02
#define USTORE_VERIFY_UPAGE_ROW 0x04
#define USTORE_VERIFY_UPAGE_ROWS 0x08
#define USTORE_VERIFY_UPAGE_MASK 0xff
#define USTORE_VERIFY_UPAGE_DEFAULT (USTORE_VERIFY_UPAGE_HEADER | USTORE_VERIFY_UPAGE_TUPLE | USTORE_VERIFY_UPAGE_ROWS)
void UpageVerify(UHeapPageHeader header, XLogRecPtr lastRedo, TupleDesc tupDesc, Relation rel,
RelFileNode* rNode, BlockNumber blkno, bool isRedo = false, uint8 mask = USTORE_VERIFY_UPAGE_DEFAULT,
OffsetNumber num = InvalidOffsetNumber);
void UpageVerifyHeader(UHeapPageHeader header, XLogRecPtr lastRedo, RelFileNode* rNode,
BlockNumber blkno, bool isRedo = false);
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/opengauss/openGauss-server.git
git@gitee.com:opengauss/openGauss-server.git
opengauss
openGauss-server
openGauss-server
master

搜索帮助