mirror of
https://github.com/postgres/postgres.git
synced 2025-08-05 07:41:25 +03:00
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:
@@ -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
|
* stack->buffer is locked on entry, and is kept locked.
|
||||||
* it contains are incremented as needed.
|
|
||||||
*
|
|
||||||
* NB: the passed-in stack is freed, as though by freeGinBtreeStack.
|
|
||||||
*/
|
*/
|
||||||
void
|
static bool
|
||||||
ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
ginPlaceToPage(GinBtree btree, BlockNumber rootBlkno, GinBtreeStack *stack,
|
||||||
|
GinStatsData *buildStats)
|
||||||
{
|
{
|
||||||
GinBtreeStack *parent;
|
Page page = BufferGetPage(stack->buffer);
|
||||||
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 (;;)
|
|
||||||
{
|
|
||||||
XLogRecData *rdata;
|
XLogRecData *rdata;
|
||||||
BlockNumber savedRightLink;
|
|
||||||
bool fit;
|
bool fit;
|
||||||
|
|
||||||
page = BufferGetPage(stack->buffer);
|
|
||||||
savedRightLink = GinPageGetOpaque(page)->rightlink;
|
|
||||||
|
|
||||||
START_CRIT_SECTION();
|
START_CRIT_SECTION();
|
||||||
fit = btree->placeToPage(btree, stack->buffer, stack->off, &rdata);
|
fit = btree->placeToPage(btree, stack->buffer, stack->off, &rdata);
|
||||||
if (fit)
|
if (fit)
|
||||||
@@ -328,23 +307,26 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
PageSetLSN(page, recptr);
|
PageSetLSN(page, recptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockBuffer(stack->buffer, GIN_UNLOCK);
|
|
||||||
END_CRIT_SECTION();
|
END_CRIT_SECTION();
|
||||||
|
|
||||||
freeGinBtreeStack(stack);
|
return true;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Didn't fit, have to split */
|
/* Didn't fit, have to split */
|
||||||
Buffer rbuffer;
|
Buffer rbuffer;
|
||||||
Page newlpage;
|
Page newlpage;
|
||||||
|
BlockNumber savedRightLink;
|
||||||
|
GinBtreeStack *parent;
|
||||||
|
Page lpage,
|
||||||
|
rpage;
|
||||||
|
|
||||||
END_CRIT_SECTION();
|
END_CRIT_SECTION();
|
||||||
|
|
||||||
rbuffer = GinNewBuffer(btree->index);
|
rbuffer = GinNewBuffer(btree->index);
|
||||||
|
|
||||||
|
savedRightLink = GinPageGetOpaque(page)->rightlink;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* newlpage is a pointer to memory page, it is not associated with
|
* newlpage is a pointer to memory page, it is not associated with
|
||||||
* a buffer. stack->buffer is not touched yet.
|
* 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))->isRootSplit = TRUE;
|
||||||
((ginxlogSplit *) (rdata->data))->rrlink = InvalidBlockNumber;
|
((ginxlogSplit *) (rdata->data))->rrlink = InvalidBlockNumber;
|
||||||
|
|
||||||
page = BufferGetPage(stack->buffer);
|
|
||||||
lpage = BufferGetPage(lbuffer);
|
lpage = BufferGetPage(lbuffer);
|
||||||
rpage = BufferGetPage(rbuffer);
|
rpage = BufferGetPage(rbuffer);
|
||||||
|
|
||||||
@@ -405,11 +386,8 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
|
|
||||||
UnlockReleaseBuffer(rbuffer);
|
UnlockReleaseBuffer(rbuffer);
|
||||||
UnlockReleaseBuffer(lbuffer);
|
UnlockReleaseBuffer(lbuffer);
|
||||||
LockBuffer(stack->buffer, GIN_UNLOCK);
|
|
||||||
END_CRIT_SECTION();
|
END_CRIT_SECTION();
|
||||||
|
|
||||||
freeGinBtreeStack(stack);
|
|
||||||
|
|
||||||
/* During index build, count the newly-added root page */
|
/* During index build, count the newly-added root page */
|
||||||
if (buildStats)
|
if (buildStats)
|
||||||
{
|
{
|
||||||
@@ -419,7 +397,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
buildStats->nEntryPages++;
|
buildStats->nEntryPages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -449,11 +427,53 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
}
|
}
|
||||||
UnlockReleaseBuffer(rbuffer);
|
UnlockReleaseBuffer(rbuffer);
|
||||||
END_CRIT_SECTION();
|
END_CRIT_SECTION();
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
btree->prepareDownlink(btree, stack->buffer);
|
||||||
btree->isDelete = FALSE;
|
|
||||||
|
|
||||||
/* search parent to lock */
|
/* search parent to lock */
|
||||||
LockBuffer(parent->buffer, GIN_EXCLUSIVE);
|
LockBuffer(parent->buffer, GIN_EXCLUSIVE);
|
||||||
|
Reference in New Issue
Block a user