Commit 04965ad4 authored by Heikki Linnakangas's avatar Heikki Linnakangas

Further GIN refactoring.

Merge some functions that were always called together. Makes the code
little bit more readable.
parent b21de4e7
...@@ -52,52 +52,38 @@ ginTraverseLock(Buffer buffer, bool searchMode) ...@@ -52,52 +52,38 @@ ginTraverseLock(Buffer buffer, bool searchMode)
return access; return access;
} }
GinBtreeStack *
ginPrepareFindLeafPage(GinBtree btree, BlockNumber blkno)
{
GinBtreeStack *stack = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
stack->blkno = blkno;
stack->buffer = ReadBuffer(btree->index, stack->blkno);
stack->parent = NULL;
stack->predictNumber = 1;
ginTraverseLock(stack->buffer, btree->searchMode);
return stack;
}
/* /*
* Locates leaf page contained tuple * Descends the tree to the leaf page that contains or would contain the
* key we're searching for. The key should already be filled in 'btree',
* in tree-type specific manner. If btree->fullScan is true, descends to the
* leftmost leaf page.
*
* If 'searchmode' is false, on return stack->buffer is exclusively locked,
* and the stack represents the full path to the root. Otherwise stack->buffer
* is share-locked, and stack->parent is NULL.
*/ */
GinBtreeStack * GinBtreeStack *
ginFindLeafPage(GinBtree btree, GinBtreeStack *stack) ginFindLeafPage(GinBtree btree, BlockNumber rootBlkno, bool searchMode)
{ {
bool isfirst = TRUE; GinBtreeStack *stack;
BlockNumber rootBlkno;
if (!stack) stack = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
stack = ginPrepareFindLeafPage(btree, GIN_ROOT_BLKNO); stack->blkno = rootBlkno;
rootBlkno = stack->blkno; stack->buffer = ReadBuffer(btree->index, rootBlkno);
stack->parent = NULL;
stack->predictNumber = 1;
for (;;) for (;;)
{ {
Page page; Page page;
BlockNumber child; BlockNumber child;
int access = GIN_SHARE; int access;
stack->off = InvalidOffsetNumber; stack->off = InvalidOffsetNumber;
page = BufferGetPage(stack->buffer); page = BufferGetPage(stack->buffer);
if (isfirst) access = ginTraverseLock(stack->buffer, searchMode);
{
if (GinPageIsLeaf(page) && !btree->searchMode)
access = GIN_EXCLUSIVE;
isfirst = FALSE;
}
else
access = ginTraverseLock(stack->buffer, btree->searchMode);
/* /*
* ok, page is correctly locked, we should check to move right .., * ok, page is correctly locked, we should check to move right ..,
...@@ -127,7 +113,7 @@ ginFindLeafPage(GinBtree btree, GinBtreeStack *stack) ...@@ -127,7 +113,7 @@ ginFindLeafPage(GinBtree btree, GinBtreeStack *stack)
Assert(child != InvalidBlockNumber); Assert(child != InvalidBlockNumber);
Assert(stack->blkno != child); Assert(stack->blkno != child);
if (btree->searchMode) if (searchMode)
{ {
/* in search mode we may forget path to leaf */ /* in search mode we may forget path to leaf */
stack->blkno = child; stack->blkno = child;
...@@ -251,7 +237,7 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack, ...@@ -251,7 +237,7 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack,
return; return;
} }
leftmostBlkno = blkno = btree->getLeftMostPage(btree, page); leftmostBlkno = blkno = btree->getLeftMostChild(btree, page);
LockBuffer(root->buffer, GIN_UNLOCK); LockBuffer(root->buffer, GIN_UNLOCK);
Assert(blkno != InvalidBlockNumber); Assert(blkno != InvalidBlockNumber);
...@@ -263,7 +249,7 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack, ...@@ -263,7 +249,7 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack,
if (GinPageIsLeaf(page)) if (GinPageIsLeaf(page))
elog(ERROR, "Lost path"); elog(ERROR, "Lost path");
leftmostBlkno = btree->getLeftMostPage(btree, page); leftmostBlkno = btree->getLeftMostChild(btree, page);
while ((offset = btree->findChildPtr(btree, page, stack->blkno, InvalidOffsetNumber)) == InvalidOffsetNumber) while ((offset = btree->findChildPtr(btree, page, stack->blkno, InvalidOffsetNumber)) == InvalidOffsetNumber)
{ {
......
...@@ -54,7 +54,7 @@ dataLocateItem(GinBtree btree, GinBtreeStack *stack) ...@@ -54,7 +54,7 @@ dataLocateItem(GinBtree btree, GinBtreeStack *stack)
{ {
stack->off = FirstOffsetNumber; stack->off = FirstOffsetNumber;
stack->predictNumber *= GinPageGetOpaque(page)->maxoff; stack->predictNumber *= GinPageGetOpaque(page)->maxoff;
return btree->getLeftMostPage(btree, page); return btree->getLeftMostChild(btree, page);
} }
low = FirstOffsetNumber; low = FirstOffsetNumber;
...@@ -680,17 +680,10 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, ...@@ -680,17 +680,10 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
*/ */
if (nitems > nrootitems) if (nitems > nrootitems)
{ {
GinPostingTreeScan *gdi; ginInsertItemPointers(index, blkno,
gdi = ginPrepareScanPostingTree(index, blkno, FALSE);
gdi->btree.isBuild = (buildStats != NULL);
ginInsertItemPointers(gdi,
items + nrootitems, items + nrootitems,
nitems - nrootitems, nitems - nrootitems,
buildStats); buildStats);
pfree(gdi);
} }
return blkno; return blkno;
...@@ -704,76 +697,69 @@ ginPrepareDataScan(GinBtree btree, Relation index) ...@@ -704,76 +697,69 @@ ginPrepareDataScan(GinBtree btree, Relation index)
btree->index = index; btree->index = index;
btree->findChildPage = dataLocateItem; btree->findChildPage = dataLocateItem;
btree->getLeftMostChild = dataGetLeftMostPage;
btree->isMoveRight = dataIsMoveRight; btree->isMoveRight = dataIsMoveRight;
btree->findItem = dataLocateLeafItem; btree->findItem = dataLocateLeafItem;
btree->findChildPtr = dataFindChildPtr; btree->findChildPtr = dataFindChildPtr;
btree->getLeftMostPage = dataGetLeftMostPage;
btree->placeToPage = dataPlaceToPage; btree->placeToPage = dataPlaceToPage;
btree->splitPage = dataSplitPage; btree->splitPage = dataSplitPage;
btree->fillRoot = ginDataFillRoot; btree->fillRoot = ginDataFillRoot;
btree->isData = TRUE; btree->isData = TRUE;
btree->searchMode = FALSE;
btree->isDelete = FALSE; btree->isDelete = FALSE;
btree->fullScan = FALSE; btree->fullScan = FALSE;
btree->isBuild = FALSE; btree->isBuild = FALSE;
} }
GinPostingTreeScan *
ginPrepareScanPostingTree(Relation index, BlockNumber rootBlkno, bool searchMode)
{
GinPostingTreeScan *gdi = (GinPostingTreeScan *) palloc0(sizeof(GinPostingTreeScan));
ginPrepareDataScan(&gdi->btree, index);
gdi->btree.searchMode = searchMode;
gdi->btree.fullScan = searchMode;
gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno);
return gdi;
}
/* /*
* Inserts array of item pointers, may execute several tree scan (very rare) * Inserts array of item pointers, may execute several tree scan (very rare)
*/ */
void void
ginInsertItemPointers(GinPostingTreeScan *gdi, ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
ItemPointerData *items, uint32 nitem, ItemPointerData *items, uint32 nitem,
GinStatsData *buildStats) GinStatsData *buildStats)
{ {
BlockNumber rootBlkno = gdi->stack->blkno; GinBtreeData btree;
GinBtreeStack *stack;
gdi->btree.items = items; ginPrepareDataScan(&btree, index);
gdi->btree.nitem = nitem; btree.isBuild = (buildStats != NULL);
gdi->btree.curitem = 0; btree.items = items;
btree.nitem = nitem;
btree.curitem = 0;
while (gdi->btree.curitem < gdi->btree.nitem) while (btree.curitem < btree.nitem)
{ {
if (!gdi->stack) stack = ginFindLeafPage(&btree, rootBlkno, false);
gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno);
gdi->stack = ginFindLeafPage(&gdi->btree, gdi->stack);
if (gdi->btree.findItem(&(gdi->btree), gdi->stack)) if (btree.findItem(&btree, stack))
{ {
/* /*
* gdi->btree.items[gdi->btree.curitem] already exists in index * btree.items[btree.curitem] already exists in index
*/ */
gdi->btree.curitem++; btree.curitem++;
LockBuffer(gdi->stack->buffer, GIN_UNLOCK); LockBuffer(stack->buffer, GIN_UNLOCK);
freeGinBtreeStack(gdi->stack); freeGinBtreeStack(stack);
} }
else else
ginInsertValue(&(gdi->btree), gdi->stack, buildStats); ginInsertValue(&btree, stack, buildStats);
gdi->stack = NULL;
} }
} }
Buffer /*
ginScanBeginPostingTree(GinPostingTreeScan *gdi) * Starts a new scan on a posting tree.
*/
GinBtreeStack *
ginScanBeginPostingTree(Relation index, BlockNumber rootBlkno)
{ {
gdi->stack = ginFindLeafPage(&gdi->btree, gdi->stack); GinBtreeData btree;
return gdi->stack->buffer; GinBtreeStack *stack;
ginPrepareDataScan(&btree, index);
btree.fullScan = TRUE;
stack = ginFindLeafPage(&btree, rootBlkno, TRUE);
return stack;
} }
...@@ -258,7 +258,7 @@ entryLocateEntry(GinBtree btree, GinBtreeStack *stack) ...@@ -258,7 +258,7 @@ entryLocateEntry(GinBtree btree, GinBtreeStack *stack)
{ {
stack->off = FirstOffsetNumber; stack->off = FirstOffsetNumber;
stack->predictNumber *= PageGetMaxOffsetNumber(page); stack->predictNumber *= PageGetMaxOffsetNumber(page);
return btree->getLeftMostPage(btree, page); return btree->getLeftMostChild(btree, page);
} }
low = FirstOffsetNumber; low = FirstOffsetNumber;
...@@ -729,16 +729,15 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, ...@@ -729,16 +729,15 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
btree->ginstate = ginstate; btree->ginstate = ginstate;
btree->findChildPage = entryLocateEntry; btree->findChildPage = entryLocateEntry;
btree->getLeftMostChild = entryGetLeftMostPage;
btree->isMoveRight = entryIsMoveRight; btree->isMoveRight = entryIsMoveRight;
btree->findItem = entryLocateLeafEntry; btree->findItem = entryLocateLeafEntry;
btree->findChildPtr = entryFindChildPtr; btree->findChildPtr = entryFindChildPtr;
btree->getLeftMostPage = entryGetLeftMostPage;
btree->placeToPage = entryPlaceToPage; btree->placeToPage = entryPlaceToPage;
btree->splitPage = entrySplitPage; btree->splitPage = entrySplitPage;
btree->fillRoot = ginEntryFillRoot; btree->fillRoot = ginEntryFillRoot;
btree->isData = FALSE; btree->isData = FALSE;
btree->searchMode = FALSE;
btree->fullScan = FALSE; btree->fullScan = FALSE;
btree->isBuild = FALSE; btree->isBuild = FALSE;
......
...@@ -124,18 +124,16 @@ static void ...@@ -124,18 +124,16 @@ static void
scanPostingTree(Relation index, GinScanEntry scanEntry, scanPostingTree(Relation index, GinScanEntry scanEntry,
BlockNumber rootPostingTree) BlockNumber rootPostingTree)
{ {
GinPostingTreeScan *gdi; GinBtreeStack *stack;
Buffer buffer; Buffer buffer;
Page page; Page page;
/* Descend to the leftmost leaf page */ /* Descend to the leftmost leaf page */
gdi = ginPrepareScanPostingTree(index, rootPostingTree, TRUE); stack = ginScanBeginPostingTree(index, rootPostingTree);
buffer = stack->buffer;
buffer = ginScanBeginPostingTree(gdi);
IncrBufferRefCount(buffer); /* prevent unpin in freeGinBtreeStack */ IncrBufferRefCount(buffer); /* prevent unpin in freeGinBtreeStack */
freeGinBtreeStack(gdi->stack); freeGinBtreeStack(stack);
pfree(gdi);
/* /*
* Loop iterates through all leaf pages of posting tree * Loop iterates through all leaf pages of posting tree
...@@ -376,8 +374,7 @@ restartScanEntry: ...@@ -376,8 +374,7 @@ restartScanEntry:
ginPrepareEntryScan(&btreeEntry, entry->attnum, ginPrepareEntryScan(&btreeEntry, entry->attnum,
entry->queryKey, entry->queryCategory, entry->queryKey, entry->queryCategory,
ginstate); ginstate);
btreeEntry.searchMode = TRUE; stackEntry = ginFindLeafPage(&btreeEntry, GIN_ROOT_BLKNO, true);
stackEntry = ginFindLeafPage(&btreeEntry, NULL);
page = BufferGetPage(stackEntry->buffer); page = BufferGetPage(stackEntry->buffer);
needUnlock = TRUE; needUnlock = TRUE;
...@@ -427,7 +424,7 @@ restartScanEntry: ...@@ -427,7 +424,7 @@ restartScanEntry:
if (GinIsPostingTree(itup)) if (GinIsPostingTree(itup))
{ {
BlockNumber rootPostingTree = GinGetPostingTree(itup); BlockNumber rootPostingTree = GinGetPostingTree(itup);
GinPostingTreeScan *gdi; GinBtreeStack *stack;
Page page; Page page;
/* /*
...@@ -439,9 +436,9 @@ restartScanEntry: ...@@ -439,9 +436,9 @@ restartScanEntry:
*/ */
LockBuffer(stackEntry->buffer, GIN_UNLOCK); LockBuffer(stackEntry->buffer, GIN_UNLOCK);
needUnlock = FALSE; needUnlock = FALSE;
gdi = ginPrepareScanPostingTree(ginstate->index, rootPostingTree, TRUE);
entry->buffer = ginScanBeginPostingTree(gdi); stack = ginScanBeginPostingTree(ginstate->index, rootPostingTree);
entry->buffer = stack->buffer;
/* /*
* We keep buffer pinned because we need to prevent deletion of * We keep buffer pinned because we need to prevent deletion of
...@@ -451,7 +448,7 @@ restartScanEntry: ...@@ -451,7 +448,7 @@ restartScanEntry:
IncrBufferRefCount(entry->buffer); IncrBufferRefCount(entry->buffer);
page = BufferGetPage(entry->buffer); page = BufferGetPage(entry->buffer);
entry->predictNumberResult = gdi->stack->predictNumber * GinPageGetOpaque(page)->maxoff; entry->predictNumberResult = stack->predictNumber * GinPageGetOpaque(page)->maxoff;
/* /*
* Keep page content in memory to prevent durable page locking * Keep page content in memory to prevent durable page locking
...@@ -463,8 +460,7 @@ restartScanEntry: ...@@ -463,8 +460,7 @@ restartScanEntry:
GinPageGetOpaque(page)->maxoff * sizeof(ItemPointerData)); GinPageGetOpaque(page)->maxoff * sizeof(ItemPointerData));
LockBuffer(entry->buffer, GIN_UNLOCK); LockBuffer(entry->buffer, GIN_UNLOCK);
freeGinBtreeStack(gdi->stack); freeGinBtreeStack(stack);
pfree(gdi);
entry->isFinished = FALSE; entry->isFinished = FALSE;
} }
else if (GinGetNPosting(itup) > 0) else if (GinGetNPosting(itup) > 0)
......
...@@ -81,7 +81,6 @@ addItemPointersToLeafTuple(GinState *ginstate, ...@@ -81,7 +81,6 @@ addItemPointersToLeafTuple(GinState *ginstate,
{ {
/* posting list would be too big, convert to posting tree */ /* posting list would be too big, convert to posting tree */
BlockNumber postingRoot; BlockNumber postingRoot;
GinPostingTreeScan *gdi;
/* /*
* Initialize posting tree with the old tuple's posting list. It's * Initialize posting tree with the old tuple's posting list. It's
...@@ -94,12 +93,9 @@ addItemPointersToLeafTuple(GinState *ginstate, ...@@ -94,12 +93,9 @@ addItemPointersToLeafTuple(GinState *ginstate,
buildStats); buildStats);
/* Now insert the TIDs-to-be-added into the posting tree */ /* Now insert the TIDs-to-be-added into the posting tree */
gdi = ginPrepareScanPostingTree(ginstate->index, postingRoot, FALSE); ginInsertItemPointers(ginstate->index, postingRoot,
gdi->btree.isBuild = (buildStats != NULL); items, nitem,
buildStats);
ginInsertItemPointers(gdi, items, nitem, buildStats);
pfree(gdi);
/* And build a new posting-tree-only result tuple */ /* And build a new posting-tree-only result tuple */
res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, true); res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, true);
...@@ -177,7 +173,7 @@ ginEntryInsert(GinState *ginstate, ...@@ -177,7 +173,7 @@ ginEntryInsert(GinState *ginstate,
ginPrepareEntryScan(&btree, attnum, key, category, ginstate); ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
stack = ginFindLeafPage(&btree, NULL); stack = ginFindLeafPage(&btree, GIN_ROOT_BLKNO, false);
page = BufferGetPage(stack->buffer); page = BufferGetPage(stack->buffer);
if (btree.findItem(&btree, stack)) if (btree.findItem(&btree, stack))
...@@ -189,18 +185,15 @@ ginEntryInsert(GinState *ginstate, ...@@ -189,18 +185,15 @@ ginEntryInsert(GinState *ginstate,
{ {
/* add entries to existing posting tree */ /* add entries to existing posting tree */
BlockNumber rootPostingTree = GinGetPostingTree(itup); BlockNumber rootPostingTree = GinGetPostingTree(itup);
GinPostingTreeScan *gdi;
/* release all stack */ /* release all stack */
LockBuffer(stack->buffer, GIN_UNLOCK); LockBuffer(stack->buffer, GIN_UNLOCK);
freeGinBtreeStack(stack); freeGinBtreeStack(stack);
/* insert into posting tree */ /* insert into posting tree */
gdi = ginPrepareScanPostingTree(ginstate->index, rootPostingTree, FALSE); ginInsertItemPointers(ginstate->index, rootPostingTree,
gdi->btree.isBuild = (buildStats != NULL); items, nitem,
ginInsertItemPointers(gdi, items, nitem, buildStats); buildStats);
pfree(gdi);
return; return;
} }
......
...@@ -479,18 +479,17 @@ typedef struct GinBtreeData ...@@ -479,18 +479,17 @@ typedef struct GinBtreeData
{ {
/* search methods */ /* search methods */
BlockNumber (*findChildPage) (GinBtree, GinBtreeStack *); BlockNumber (*findChildPage) (GinBtree, GinBtreeStack *);
BlockNumber (*getLeftMostChild) (GinBtree, Page);
bool (*isMoveRight) (GinBtree, Page); bool (*isMoveRight) (GinBtree, Page);
bool (*findItem) (GinBtree, GinBtreeStack *); bool (*findItem) (GinBtree, GinBtreeStack *);
/* insert methods */ /* insert methods */
OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber); OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
BlockNumber (*getLeftMostPage) (GinBtree, Page);
bool (*placeToPage) (GinBtree, Buffer, OffsetNumber, XLogRecData **); bool (*placeToPage) (GinBtree, Buffer, OffsetNumber, XLogRecData **);
Page (*splitPage) (GinBtree, Buffer, Buffer, OffsetNumber, XLogRecData **); Page (*splitPage) (GinBtree, Buffer, Buffer, OffsetNumber, XLogRecData **);
void (*fillRoot) (GinBtree, Buffer, Buffer, Buffer); void (*fillRoot) (GinBtree, Buffer, Buffer, Buffer);
bool isData; bool isData;
bool searchMode;
Relation index; Relation index;
GinState *ginstate; /* not valid in a data scan */ GinState *ginstate; /* not valid in a data scan */
...@@ -514,8 +513,7 @@ typedef struct GinBtreeData ...@@ -514,8 +513,7 @@ typedef struct GinBtreeData
PostingItem pitem; PostingItem pitem;
} GinBtreeData; } GinBtreeData;
extern GinBtreeStack *ginPrepareFindLeafPage(GinBtree btree, BlockNumber blkno); extern GinBtreeStack *ginFindLeafPage(GinBtree btree, BlockNumber rootBlkno, bool searchMode);
extern GinBtreeStack *ginFindLeafPage(GinBtree btree, GinBtreeStack *stack);
extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode); extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode);
extern void freeGinBtreeStack(GinBtreeStack *stack); extern void freeGinBtreeStack(GinBtreeStack *stack);
extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack, extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack,
...@@ -540,19 +538,10 @@ extern BlockNumber createPostingTree(Relation index, ...@@ -540,19 +538,10 @@ extern BlockNumber createPostingTree(Relation index,
extern void GinDataPageAddItemPointer(Page page, ItemPointer data, OffsetNumber offset); extern void GinDataPageAddItemPointer(Page page, ItemPointer data, OffsetNumber offset);
extern void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset); extern void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset);
extern void GinPageDeletePostingItem(Page page, OffsetNumber offset); extern void GinPageDeletePostingItem(Page page, OffsetNumber offset);
extern void ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
typedef struct
{
GinBtreeData btree;
GinBtreeStack *stack;
} GinPostingTreeScan;
extern GinPostingTreeScan *ginPrepareScanPostingTree(Relation index,
BlockNumber rootBlkno, bool searchMode);
extern void ginInsertItemPointers(GinPostingTreeScan *gdi,
ItemPointerData *items, uint32 nitem, ItemPointerData *items, uint32 nitem,
GinStatsData *buildStats); GinStatsData *buildStats);
extern Buffer ginScanBeginPostingTree(GinPostingTreeScan *gdi); extern GinBtreeStack *ginScanBeginPostingTree(Relation index, BlockNumber rootBlkno);
extern void ginDataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf); extern void ginDataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
extern void ginPrepareDataScan(GinBtree btree, Relation index); extern void ginPrepareDataScan(GinBtree btree, Relation index);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment