📄 gindatapage.c
字号:
/*------------------------------------------------------------------------- * * gindatapage.c * page utilities routines for the postgres inverted index access method. * * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/access/gin/gindatapage.c,v 1.9 2008/01/01 19:45:46 momjian Exp $ *------------------------------------------------------------------------- */#include "postgres.h"#include "access/gin.h"intcompareItemPointers(ItemPointer a, ItemPointer b){ if (GinItemPointerGetBlockNumber(a) == GinItemPointerGetBlockNumber(b)) { if (GinItemPointerGetOffsetNumber(a) == GinItemPointerGetOffsetNumber(b)) return 0; return (GinItemPointerGetOffsetNumber(a) > GinItemPointerGetOffsetNumber(b)) ? 1 : -1; } return (GinItemPointerGetBlockNumber(a) > GinItemPointerGetBlockNumber(b)) ? 1 : -1;}/* * Merge two ordered array of itempointer */voidMergeItemPointers(ItemPointerData *dst, ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb){ ItemPointerData *dptr = dst; ItemPointerData *aptr = a, *bptr = b; while (aptr - a < na && bptr - b < nb) { if (compareItemPointers(aptr, bptr) > 0) *dptr++ = *bptr++; else *dptr++ = *aptr++; } while (aptr - a < na) *dptr++ = *aptr++; while (bptr - b < nb) *dptr++ = *bptr++;}/* * Checks, should we move to right link... * Compares inserting itemp pointer with right bound of current page */static booldataIsMoveRight(GinBtree btree, Page page){ ItemPointer iptr = GinDataPageGetRightBound(page); if (GinPageRightMost(page)) return FALSE; return (compareItemPointers(btree->items + btree->curitem, iptr) > 0) ? TRUE : FALSE;}/* * Find correct PostingItem in non-leaf page. It supposed that page * correctly chosen and searching value SHOULD be on page */static BlockNumberdataLocateItem(GinBtree btree, GinBtreeStack *stack){ OffsetNumber low, high, maxoff; PostingItem *pitem = NULL; int result; Page page = BufferGetPage(stack->buffer); Assert(!GinPageIsLeaf(page)); Assert(GinPageIsData(page)); if (btree->fullScan) { stack->off = FirstOffsetNumber; stack->predictNumber *= GinPageGetOpaque(page)->maxoff; return btree->getLeftMostPage(btree, page); } low = FirstOffsetNumber; maxoff = high = GinPageGetOpaque(page)->maxoff; Assert(high >= low); high++; while (high > low) { OffsetNumber mid = low + ((high - low) / 2); pitem = (PostingItem *) GinDataPageGetItem(page, mid); if (mid == maxoff) /* * Right infinity, page already correctly chosen with a help of * dataIsMoveRight */ result = -1; else { pitem = (PostingItem *) GinDataPageGetItem(page, mid); result = compareItemPointers(btree->items + btree->curitem, &(pitem->key)); } if (result == 0) { stack->off = mid; return PostingItemGetBlockNumber(pitem); } else if (result > 0) low = mid + 1; else high = mid; } Assert(high >= FirstOffsetNumber && high <= maxoff); stack->off = high; pitem = (PostingItem *) GinDataPageGetItem(page, high); return PostingItemGetBlockNumber(pitem);}/* * Searches correct position for value on leaf page. * Page should be correctly chosen. * Returns true if value found on page. */static booldataLocateLeafItem(GinBtree btree, GinBtreeStack *stack){ Page page = BufferGetPage(stack->buffer); OffsetNumber low, high; int result; Assert(GinPageIsLeaf(page)); Assert(GinPageIsData(page)); if (btree->fullScan) { stack->off = FirstOffsetNumber; return TRUE; } low = FirstOffsetNumber; high = GinPageGetOpaque(page)->maxoff; if (high < low) { stack->off = FirstOffsetNumber; return false; } high++; while (high > low) { OffsetNumber mid = low + ((high - low) / 2); result = compareItemPointers(btree->items + btree->curitem, (ItemPointer) GinDataPageGetItem(page, mid)); if (result == 0) { stack->off = mid; return true; } else if (result > 0) low = mid + 1; else high = mid; } stack->off = high; return false;}/* * Finds links to blkno on non-leaf page, returns * offset of PostingItem */static OffsetNumberdataFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber storedOff){ OffsetNumber i, maxoff = GinPageGetOpaque(page)->maxoff; PostingItem *pitem; Assert(!GinPageIsLeaf(page)); Assert(GinPageIsData(page)); /* if page isn't changed, we returns storedOff */ if (storedOff >= FirstOffsetNumber && storedOff <= maxoff) { pitem = (PostingItem *) GinDataPageGetItem(page, storedOff); if (PostingItemGetBlockNumber(pitem) == blkno) return storedOff; /* * we hope, that needed pointer goes to right. It's true if there * wasn't a deletion */ for (i = storedOff + 1; i <= maxoff; i++) { pitem = (PostingItem *) GinDataPageGetItem(page, i); if (PostingItemGetBlockNumber(pitem) == blkno) return i; } maxoff = storedOff - 1; } /* last chance */ for (i = FirstOffsetNumber; i <= maxoff; i++) { pitem = (PostingItem *) GinDataPageGetItem(page, i); if (PostingItemGetBlockNumber(pitem) == blkno) return i; } return InvalidOffsetNumber;}/* * returns blkno of leftmost child */static BlockNumberdataGetLeftMostPage(GinBtree btree, Page page){ PostingItem *pitem; Assert(!GinPageIsLeaf(page)); Assert(GinPageIsData(page)); Assert(GinPageGetOpaque(page)->maxoff >= FirstOffsetNumber); pitem = (PostingItem *) GinDataPageGetItem(page, FirstOffsetNumber); return PostingItemGetBlockNumber(pitem);}/* * add ItemPointer or PostingItem to page. data should point to * correct value! depending on leaf or non-leaf page */voidGinDataPageAddItem(Page page, void *data, OffsetNumber offset){ OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff; char *ptr; if (offset == InvalidOffsetNumber) { ptr = GinDataPageGetItem(page, maxoff + 1); } else { ptr = GinDataPageGetItem(page, offset); if (maxoff + 1 - offset != 0) memmove(ptr + GinSizeOfItem(page), ptr, (maxoff - offset + 1) * GinSizeOfItem(page)); } memcpy(ptr, data, GinSizeOfItem(page)); GinPageGetOpaque(page)->maxoff++;}/* * Deletes posting item from non-leaf page */voidPageDeletePostingItem(Page page, OffsetNumber offset){ OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff; Assert(!GinPageIsLeaf(page)); Assert(offset >= FirstOffsetNumber && offset <= maxoff); if (offset != maxoff) memmove(GinDataPageGetItem(page, offset), GinDataPageGetItem(page, offset + 1), sizeof(PostingItem) * (maxoff - offset)); GinPageGetOpaque(page)->maxoff--;}/* * checks space to install new value, * item pointer never deletes! */static booldataIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off){ Page page = BufferGetPage(buf); Assert(GinPageIsData(page)); Assert(!btree->isDelete); if (GinPageIsLeaf(page)) { if (GinPageRightMost(page) && off > GinPageGetOpaque(page)->maxoff) { if ((btree->nitem - btree->curitem) * sizeof(ItemPointerData) <= GinDataPageGetFreeSpace(page)) return true; } else if (sizeof(ItemPointerData) <= GinDataPageGetFreeSpace(page)) return true; } else if (sizeof(PostingItem) <= GinDataPageGetFreeSpace(page)) return true; return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -