Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 04eee1f

Browse files
committed
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.
1 parent 5010126 commit 04eee1f

File tree

1 file changed

+148
-128
lines changed

1 file changed

+148
-128
lines changed

src/backend/access/gin/ginbtree.c

Lines changed: 148 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -280,80 +280,115 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack,
280280
}
281281

282282
/*
283-
* Insert value (stored in GinBtree) to tree described by stack
284-
*
285-
* During an index build, buildStats is non-null and the counters
286-
* it contains are incremented as needed.
283+
* Returns true if the insertion is done, false if the page was split and
284+
* downlink insertion is pending.
287285
*
288-
* NB: the passed-in stack is freed, as though by freeGinBtreeStack.
286+
* stack->buffer is locked on entry, and is kept locked.
289287
*/
290-
void
291-
ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
288+
static bool
289+
ginPlaceToPage(GinBtree btree, BlockNumber rootBlkno, GinBtreeStack *stack,
290+
GinStatsData *buildStats)
292291
{
293-
GinBtreeStack *parent;
294-
BlockNumber rootBlkno;
295-
Page page,
296-
rpage,
297-
lpage;
292+
Page page = BufferGetPage(stack->buffer);
293+
XLogRecData *rdata;
294+
bool fit;
298295

299-
/* extract root BlockNumber from stack */
300-
Assert(stack != NULL);
301-
parent = stack;
302-
while (parent->parent)
303-
parent = parent->parent;
304-
rootBlkno = parent->blkno;
305-
Assert(BlockNumberIsValid(rootBlkno));
296+
START_CRIT_SECTION();
297+
fit = btree->placeToPage(btree, stack->buffer, stack->off, &rdata);
298+
if (fit)
299+
{
300+
MarkBufferDirty(stack->buffer);
306301

307-
/* this loop crawls up the stack until the insertion is complete */
308-
for (;;)
302+
if (RelationNeedsWAL(btree->index))
303+
{
304+
XLogRecPtr recptr;
305+
306+
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_INSERT, rdata);
307+
PageSetLSN(page, recptr);
308+
}
309+
310+
END_CRIT_SECTION();
311+
312+
return true;
313+
}
314+
else
309315
{
310-
XLogRecData *rdata;
316+
/* Didn't fit, have to split */
317+
Buffer rbuffer;
318+
Page newlpage;
311319
BlockNumber savedRightLink;
312-
bool fit;
320+
GinBtreeStack *parent;
321+
Page lpage,
322+
rpage;
323+
324+
END_CRIT_SECTION();
325+
326+
rbuffer = GinNewBuffer(btree->index);
313327

314-
page = BufferGetPage(stack->buffer);
315328
savedRightLink = GinPageGetOpaque(page)->rightlink;
316329

317-
START_CRIT_SECTION();
318-
fit = btree->placeToPage(btree, stack->buffer, stack->off, &rdata);
319-
if (fit)
330+
/*
331+
* newlpage is a pointer to memory page, it is not associated with
332+
* a buffer. stack->buffer is not touched yet.
333+
*/
334+
newlpage = btree->splitPage(btree, stack->buffer, rbuffer, stack->off, &rdata);
335+
336+
((ginxlogSplit *) (rdata->data))->rootBlkno = rootBlkno;
337+
338+
/* During index build, count the newly-split page */
339+
if (buildStats)
320340
{
341+
if (btree->isData)
342+
buildStats->nDataPages++;
343+
else
344+
buildStats->nEntryPages++;
345+
}
346+
347+
parent = stack->parent;
348+
349+
if (parent == NULL)
350+
{
351+
/*
352+
* split root, so we need to allocate new left page and place
353+
* pointer on root to left and right page
354+
*/
355+
Buffer lbuffer = GinNewBuffer(btree->index);
356+
357+
((ginxlogSplit *) (rdata->data))->isRootSplit = TRUE;
358+
((ginxlogSplit *) (rdata->data))->rrlink = InvalidBlockNumber;
359+
360+
lpage = BufferGetPage(lbuffer);
361+
rpage = BufferGetPage(rbuffer);
362+
363+
GinPageGetOpaque(rpage)->rightlink = InvalidBlockNumber;
364+
GinPageGetOpaque(newlpage)->rightlink = BufferGetBlockNumber(rbuffer);
365+
((ginxlogSplit *) (rdata->data))->lblkno = BufferGetBlockNumber(lbuffer);
366+
367+
START_CRIT_SECTION();
368+
369+
GinInitBuffer(stack->buffer, GinPageGetOpaque(newlpage)->flags & ~GIN_LEAF);
370+
PageRestoreTempPage(newlpage, lpage);
371+
btree->fillRoot(btree, stack->buffer, lbuffer, rbuffer);
372+
373+
MarkBufferDirty(rbuffer);
374+
MarkBufferDirty(lbuffer);
321375
MarkBufferDirty(stack->buffer);
322376

323377
if (RelationNeedsWAL(btree->index))
324378
{
325379
XLogRecPtr recptr;
326380

327-
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_INSERT, rdata);
381+
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_SPLIT, rdata);
328382
PageSetLSN(page, recptr);
383+
PageSetLSN(lpage, recptr);
384+
PageSetLSN(rpage, recptr);
329385
}
330386

331-
LockBuffer(stack->buffer, GIN_UNLOCK);
332-
END_CRIT_SECTION();
333-
334-
freeGinBtreeStack(stack);
335-
336-
return;
337-
}
338-
else
339-
{
340-
/* Didn't fit, have to split */
341-
Buffer rbuffer;
342-
Page newlpage;
343-
387+
UnlockReleaseBuffer(rbuffer);
388+
UnlockReleaseBuffer(lbuffer);
344389
END_CRIT_SECTION();
345390

346-
rbuffer = GinNewBuffer(btree->index);
347-
348-
/*
349-
* newlpage is a pointer to memory page, it is not associated with
350-
* a buffer. stack->buffer is not touched yet.
351-
*/
352-
newlpage = btree->splitPage(btree, stack->buffer, rbuffer, stack->off, &rdata);
353-
354-
((ginxlogSplit *) (rdata->data))->rootBlkno = rootBlkno;
355-
356-
/* During index build, count the newly-split page */
391+
/* During index build, count the newly-added root page */
357392
if (buildStats)
358393
{
359394
if (btree->isData)
@@ -362,98 +397,83 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
362397
buildStats->nEntryPages++;
363398
}
364399

365-
parent = stack->parent;
366-
367-
if (parent == NULL)
368-
{
369-
/*
370-
* split root, so we need to allocate new left page and place
371-
* pointer on root to left and right page
372-
*/
373-
Buffer lbuffer = GinNewBuffer(btree->index);
374-
375-
((ginxlogSplit *) (rdata->data))->isRootSplit = TRUE;
376-
((ginxlogSplit *) (rdata->data))->rrlink = InvalidBlockNumber;
377-
378-
page = BufferGetPage(stack->buffer);
379-
lpage = BufferGetPage(lbuffer);
380-
rpage = BufferGetPage(rbuffer);
381-
382-
GinPageGetOpaque(rpage)->rightlink = InvalidBlockNumber;
383-
GinPageGetOpaque(newlpage)->rightlink = BufferGetBlockNumber(rbuffer);
384-
((ginxlogSplit *) (rdata->data))->lblkno = BufferGetBlockNumber(lbuffer);
385-
386-
START_CRIT_SECTION();
387-
388-
GinInitBuffer(stack->buffer, GinPageGetOpaque(newlpage)->flags & ~GIN_LEAF);
389-
PageRestoreTempPage(newlpage, lpage);
390-
btree->fillRoot(btree, stack->buffer, lbuffer, rbuffer);
391-
392-
MarkBufferDirty(rbuffer);
393-
MarkBufferDirty(lbuffer);
394-
MarkBufferDirty(stack->buffer);
400+
return true;
401+
}
402+
else
403+
{
404+
/* split non-root page */
405+
((ginxlogSplit *) (rdata->data))->isRootSplit = FALSE;
406+
((ginxlogSplit *) (rdata->data))->rrlink = savedRightLink;
395407

396-
if (RelationNeedsWAL(btree->index))
397-
{
398-
XLogRecPtr recptr;
408+
lpage = BufferGetPage(stack->buffer);
409+
rpage = BufferGetPage(rbuffer);
399410

400-
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_SPLIT, rdata);
401-
PageSetLSN(page, recptr);
402-
PageSetLSN(lpage, recptr);
403-
PageSetLSN(rpage, recptr);
404-
}
411+
GinPageGetOpaque(rpage)->rightlink = savedRightLink;
412+
GinPageGetOpaque(newlpage)->rightlink = BufferGetBlockNumber(rbuffer);
405413

406-
UnlockReleaseBuffer(rbuffer);
407-
UnlockReleaseBuffer(lbuffer);
408-
LockBuffer(stack->buffer, GIN_UNLOCK);
409-
END_CRIT_SECTION();
414+
START_CRIT_SECTION();
415+
PageRestoreTempPage(newlpage, lpage);
410416

411-
freeGinBtreeStack(stack);
417+
MarkBufferDirty(rbuffer);
418+
MarkBufferDirty(stack->buffer);
412419

413-
/* During index build, count the newly-added root page */
414-
if (buildStats)
415-
{
416-
if (btree->isData)
417-
buildStats->nDataPages++;
418-
else
419-
buildStats->nEntryPages++;
420-
}
420+
if (RelationNeedsWAL(btree->index))
421+
{
422+
XLogRecPtr recptr;
421423

422-
return;
424+
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_SPLIT, rdata);
425+
PageSetLSN(lpage, recptr);
426+
PageSetLSN(rpage, recptr);
423427
}
424-
else
425-
{
426-
/* split non-root page */
427-
((ginxlogSplit *) (rdata->data))->isRootSplit = FALSE;
428-
((ginxlogSplit *) (rdata->data))->rrlink = savedRightLink;
428+
UnlockReleaseBuffer(rbuffer);
429+
END_CRIT_SECTION();
429430

430-
lpage = BufferGetPage(stack->buffer);
431-
rpage = BufferGetPage(rbuffer);
431+
return false;
432+
}
433+
}
434+
}
432435

433-
GinPageGetOpaque(rpage)->rightlink = savedRightLink;
434-
GinPageGetOpaque(newlpage)->rightlink = BufferGetBlockNumber(rbuffer);
436+
/*
437+
* Insert value (stored in GinBtree) to tree described by stack
438+
*
439+
* During an index build, buildStats is non-null and the counters
440+
* it contains are incremented as needed.
441+
*
442+
* NB: the passed-in stack is freed, as though by freeGinBtreeStack.
443+
*/
444+
void
445+
ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
446+
{
447+
GinBtreeStack *parent;
448+
BlockNumber rootBlkno;
449+
Page page;
450+
451+
/* extract root BlockNumber from stack */
452+
Assert(stack != NULL);
453+
parent = stack;
454+
while (parent->parent)
455+
parent = parent->parent;
456+
rootBlkno = parent->blkno;
457+
Assert(BlockNumberIsValid(rootBlkno));
435458

436-
START_CRIT_SECTION();
437-
PageRestoreTempPage(newlpage, lpage);
459+
/* this loop crawls up the stack until the insertion is complete */
460+
for (;;)
461+
{
462+
bool done;
438463

439-
MarkBufferDirty(rbuffer);
440-
MarkBufferDirty(stack->buffer);
464+
done = ginPlaceToPage(btree, rootBlkno, stack, buildStats);
441465

442-
if (RelationNeedsWAL(btree->index))
443-
{
444-
XLogRecPtr recptr;
466+
/* just to be extra sure we don't delete anything by accident... */
467+
btree->isDelete = FALSE;
445468

446-
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_SPLIT, rdata);
447-
PageSetLSN(lpage, recptr);
448-
PageSetLSN(rpage, recptr);
449-
}
450-
UnlockReleaseBuffer(rbuffer);
451-
END_CRIT_SECTION();
452-
}
469+
if (done)
470+
{
471+
LockBuffer(stack->buffer, GIN_UNLOCK);
472+
freeGinBtreeStack(stack);
473+
break;
453474
}
454475

455476
btree->prepareDownlink(btree, stack->buffer);
456-
btree->isDelete = FALSE;
457477

458478
/* search parent to lock */
459479
LockBuffer(parent->buffer, GIN_EXCLUSIVE);

0 commit comments

Comments
 (0)