More GIN refactoring.

Split off the portion of ginInsertValue that inserts the tuple to current
level into a separate function, ginPlaceToPage. ginInsertValue's charter
is now to recurse up the tree to insert the downlink, when a page split is
required.

This is in preparation for a patch to change the way incomplete splits are
handled, which will need to do these operations separately. And IMHO makes
the code more readable anyway.
This commit is contained in:
Heikki Linnakangas 2013-11-20 17:00:53 +02:00
parent 501012631e
commit 04eee1fa9e

View File

@ -280,40 +280,19 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack,
}
/*
* Insert value (stored in GinBtree) to tree described by stack
* Returns true if the insertion is done, false if the page was split and
* downlink insertion is pending.
*
* During an index build, buildStats is non-null and the counters
* it contains are incremented as needed.
*
* NB: the passed-in stack is freed, as though by freeGinBtreeStack.
* stack->buffer is locked on entry, and is kept locked.
*/
void
ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
{
GinBtreeStack *parent;
BlockNumber rootBlkno;
Page page,
rpage,
lpage;
/* extract root BlockNumber from stack */
Assert(stack != NULL);
parent = stack;
while (parent->parent)
parent = parent->parent;
rootBlkno = parent->blkno;
Assert(BlockNumberIsValid(rootBlkno));
/* this loop crawls up the stack until the insertion is complete */
for (;;)
static bool
ginPlaceToPage(GinBtree btree, BlockNumber rootBlkno, GinBtreeStack *stack,
GinStatsData *buildStats)
{
Page page = BufferGetPage(stack->buffer);
XLogRecData *rdata;
BlockNumber savedRightLink;
bool fit;
page = BufferGetPage(stack->buffer);
savedRightLink = GinPageGetOpaque(page)->rightlink;
START_CRIT_SECTION();
fit = btree->placeToPage(btree, stack->buffer, stack->off, &rdata);
if (fit)
@ -328,23 +307,26 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
PageSetLSN(page, recptr);
}
LockBuffer(stack->buffer, GIN_UNLOCK);
END_CRIT_SECTION();
freeGinBtreeStack(stack);
return;
return true;
}
else
{
/* Didn't fit, have to split */
Buffer rbuffer;
Page newlpage;
BlockNumber savedRightLink;
GinBtreeStack *parent;
Page lpage,
rpage;
END_CRIT_SECTION();
rbuffer = GinNewBuffer(btree->index);
savedRightLink = GinPageGetOpaque(page)->rightlink;
/*
* newlpage is a pointer to memory page, it is not associated with
* a buffer. stack->buffer is not touched yet.
@ -375,7 +357,6 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
((ginxlogSplit *) (rdata->data))->isRootSplit = TRUE;
((ginxlogSplit *) (rdata->data))->rrlink = InvalidBlockNumber;
page = BufferGetPage(stack->buffer);
lpage = BufferGetPage(lbuffer);
rpage = BufferGetPage(rbuffer);
@ -405,11 +386,8 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
UnlockReleaseBuffer(rbuffer);
UnlockReleaseBuffer(lbuffer);
LockBuffer(stack->buffer, GIN_UNLOCK);
END_CRIT_SECTION();
freeGinBtreeStack(stack);
/* During index build, count the newly-added root page */
if (buildStats)
{
@ -419,7 +397,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
buildStats->nEntryPages++;
}
return;
return true;
}
else
{
@ -449,12 +427,54 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
}
UnlockReleaseBuffer(rbuffer);
END_CRIT_SECTION();
return false;
}
}
}
btree->prepareDownlink(btree, stack->buffer);
/*
* Insert value (stored in GinBtree) to tree described by stack
*
* During an index build, buildStats is non-null and the counters
* it contains are incremented as needed.
*
* NB: the passed-in stack is freed, as though by freeGinBtreeStack.
*/
void
ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
{
GinBtreeStack *parent;
BlockNumber rootBlkno;
Page page;
/* extract root BlockNumber from stack */
Assert(stack != NULL);
parent = stack;
while (parent->parent)
parent = parent->parent;
rootBlkno = parent->blkno;
Assert(BlockNumberIsValid(rootBlkno));
/* this loop crawls up the stack until the insertion is complete */
for (;;)
{
bool done;
done = ginPlaceToPage(btree, rootBlkno, stack, buildStats);
/* just to be extra sure we don't delete anything by accident... */
btree->isDelete = FALSE;
if (done)
{
LockBuffer(stack->buffer, GIN_UNLOCK);
freeGinBtreeStack(stack);
break;
}
btree->prepareDownlink(btree, stack->buffer);
/* search parent to lock */
LockBuffer(parent->buffer, GIN_EXCLUSIVE);