Refactor the internal GIN B-tree interface for forming a downlink.
This creates a new gin-btree callback function for creating a downlink for a page. Previously, ginxlog.c duplicated the logic used during normal operation.
This commit is contained in:
parent
04965ad40e
commit
501012631e
src
@ -452,6 +452,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btree->prepareDownlink(btree, stack->buffer);
|
||||||
btree->isDelete = FALSE;
|
btree->isDelete = FALSE;
|
||||||
|
|
||||||
/* search parent to lock */
|
/* search parent to lock */
|
||||||
|
@ -580,12 +580,20 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe
|
|||||||
rdata[1].len = MAXALIGN(maxoff * sizeofitem);
|
rdata[1].len = MAXALIGN(maxoff * sizeofitem);
|
||||||
rdata[1].next = NULL;
|
rdata[1].next = NULL;
|
||||||
|
|
||||||
/* Prepare a downlink tuple for insertion to the parent */
|
return lpage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the state in 'btree' for inserting a downlink for given buffer.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
dataPrepareDownlink(GinBtree btree, Buffer lbuf)
|
||||||
|
{
|
||||||
|
Page lpage = BufferGetPage(lbuf);
|
||||||
|
|
||||||
PostingItemSetBlockNumber(&(btree->pitem), BufferGetBlockNumber(lbuf));
|
PostingItemSetBlockNumber(&(btree->pitem), BufferGetBlockNumber(lbuf));
|
||||||
btree->pitem.key = *GinDataPageGetRightBound(lpage);
|
btree->pitem.key = *GinDataPageGetRightBound(lpage);
|
||||||
btree->rightblkno = BufferGetBlockNumber(rbuf);
|
btree->rightblkno = GinPageGetOpaque(lpage)->rightlink;
|
||||||
|
|
||||||
return lpage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -704,6 +712,7 @@ ginPrepareDataScan(GinBtree btree, Relation index)
|
|||||||
btree->placeToPage = dataPlaceToPage;
|
btree->placeToPage = dataPlaceToPage;
|
||||||
btree->splitPage = dataSplitPage;
|
btree->splitPage = dataSplitPage;
|
||||||
btree->fillRoot = ginDataFillRoot;
|
btree->fillRoot = ginDataFillRoot;
|
||||||
|
btree->prepareDownlink = dataPrepareDownlink;
|
||||||
|
|
||||||
btree->isData = TRUE;
|
btree->isData = TRUE;
|
||||||
btree->isDelete = FALSE;
|
btree->isDelete = FALSE;
|
||||||
|
@ -570,8 +570,7 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
|
|||||||
Size lsize = 0,
|
Size lsize = 0,
|
||||||
size;
|
size;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
IndexTuple itup,
|
IndexTuple itup;
|
||||||
leftrightmost = NULL;
|
|
||||||
Page page;
|
Page page;
|
||||||
Page lpage = PageGetTempPageCopy(BufferGetPage(lbuf));
|
Page lpage = PageGetTempPageCopy(BufferGetPage(lbuf));
|
||||||
Page rpage = BufferGetPage(rbuf);
|
Page rpage = BufferGetPage(rbuf);
|
||||||
@ -635,7 +634,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
leftrightmost = itup;
|
|
||||||
lsize += MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
|
lsize += MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,11 +643,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
|
|||||||
ptr += MAXALIGN(IndexTupleSize(itup));
|
ptr += MAXALIGN(IndexTupleSize(itup));
|
||||||
}
|
}
|
||||||
|
|
||||||
btree->entry = GinFormInteriorTuple(leftrightmost, lpage,
|
|
||||||
BufferGetBlockNumber(lbuf));
|
|
||||||
|
|
||||||
btree->rightblkno = BufferGetBlockNumber(rbuf);
|
|
||||||
|
|
||||||
data.node = btree->index->rd_node;
|
data.node = btree->index->rd_node;
|
||||||
data.rootBlkno = InvalidBlockNumber;
|
data.rootBlkno = InvalidBlockNumber;
|
||||||
data.lblkno = BufferGetBlockNumber(lbuf);
|
data.lblkno = BufferGetBlockNumber(lbuf);
|
||||||
@ -674,19 +667,20 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return newly allocated rightmost tuple
|
* Prepare the state in 'btree' for inserting a downlink for given buffer.
|
||||||
*/
|
*/
|
||||||
IndexTuple
|
static void
|
||||||
ginPageGetLinkItup(Buffer buf)
|
entryPrepareDownlink(GinBtree btree, Buffer lbuf)
|
||||||
{
|
{
|
||||||
IndexTuple itup,
|
Page lpage = BufferGetPage(lbuf);
|
||||||
nitup;
|
IndexTuple itup;
|
||||||
Page page = BufferGetPage(buf);
|
|
||||||
|
|
||||||
itup = getRightMostTuple(page);
|
itup = getRightMostTuple(lpage);
|
||||||
nitup = GinFormInteriorTuple(itup, page, BufferGetBlockNumber(buf));
|
|
||||||
|
|
||||||
return nitup;
|
btree->entry = GinFormInteriorTuple(itup,
|
||||||
|
lpage,
|
||||||
|
BufferGetBlockNumber(lbuf));
|
||||||
|
btree->rightblkno = GinPageGetOpaque(lpage)->rightlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -696,17 +690,21 @@ ginPageGetLinkItup(Buffer buf)
|
|||||||
void
|
void
|
||||||
ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf)
|
ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf)
|
||||||
{
|
{
|
||||||
Page page;
|
Page page = BufferGetPage(root);
|
||||||
|
Page lpage = BufferGetPage(lbuf);
|
||||||
|
Page rpage = BufferGetPage(rbuf);
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
|
|
||||||
page = BufferGetPage(root);
|
itup = GinFormInteriorTuple(getRightMostTuple(lpage),
|
||||||
|
lpage,
|
||||||
itup = ginPageGetLinkItup(lbuf);
|
BufferGetBlockNumber(lbuf));
|
||||||
if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
|
if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
|
||||||
elog(ERROR, "failed to add item to index root page");
|
elog(ERROR, "failed to add item to index root page");
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
|
|
||||||
itup = ginPageGetLinkItup(rbuf);
|
itup = GinFormInteriorTuple(getRightMostTuple(rpage),
|
||||||
|
rpage,
|
||||||
|
BufferGetBlockNumber(rbuf));
|
||||||
if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
|
if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
|
||||||
elog(ERROR, "failed to add item to index root page");
|
elog(ERROR, "failed to add item to index root page");
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
@ -736,6 +734,7 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
|
|||||||
btree->placeToPage = entryPlaceToPage;
|
btree->placeToPage = entryPlaceToPage;
|
||||||
btree->splitPage = entrySplitPage;
|
btree->splitPage = entrySplitPage;
|
||||||
btree->fillRoot = ginEntryFillRoot;
|
btree->fillRoot = ginEntryFillRoot;
|
||||||
|
btree->prepareDownlink = entryPrepareDownlink;
|
||||||
|
|
||||||
btree->isData = FALSE;
|
btree->isData = FALSE;
|
||||||
btree->fullScan = FALSE;
|
btree->fullScan = FALSE;
|
||||||
|
@ -799,31 +799,20 @@ ginContinueSplit(ginIncompleteSplit *split)
|
|||||||
ginPrepareEntryScan(&btree,
|
ginPrepareEntryScan(&btree,
|
||||||
InvalidOffsetNumber, (Datum) 0, GIN_CAT_NULL_KEY,
|
InvalidOffsetNumber, (Datum) 0, GIN_CAT_NULL_KEY,
|
||||||
&ginstate);
|
&ginstate);
|
||||||
btree.entry = ginPageGetLinkItup(buffer);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Page page = BufferGetPage(buffer);
|
|
||||||
|
|
||||||
ginPrepareDataScan(&btree, reln);
|
ginPrepareDataScan(&btree, reln);
|
||||||
|
|
||||||
PostingItemSetBlockNumber(&(btree.pitem), split->leftBlkno);
|
|
||||||
if (GinPageIsLeaf(page))
|
|
||||||
btree.pitem.key = *GinDataPageGetItemPointer(page,
|
|
||||||
GinPageGetOpaque(page)->maxoff);
|
|
||||||
else
|
|
||||||
btree.pitem.key = GinDataPageGetPostingItem(page,
|
|
||||||
GinPageGetOpaque(page)->maxoff)->key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btree.rightblkno = split->rightBlkno;
|
|
||||||
|
|
||||||
stack.blkno = split->leftBlkno;
|
stack.blkno = split->leftBlkno;
|
||||||
stack.buffer = buffer;
|
stack.buffer = buffer;
|
||||||
stack.off = InvalidOffsetNumber;
|
stack.off = InvalidOffsetNumber;
|
||||||
stack.parent = NULL;
|
stack.parent = NULL;
|
||||||
|
|
||||||
ginFindParents(&btree, &stack, split->rootBlkno);
|
ginFindParents(&btree, &stack, split->rootBlkno);
|
||||||
|
|
||||||
|
btree.prepareDownlink(&btree, buffer);
|
||||||
ginInsertValue(&btree, stack.parent, NULL);
|
ginInsertValue(&btree, stack.parent, NULL);
|
||||||
|
|
||||||
FreeFakeRelcacheEntry(reln);
|
FreeFakeRelcacheEntry(reln);
|
||||||
|
@ -487,6 +487,7 @@ typedef struct GinBtreeData
|
|||||||
OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
|
OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
|
||||||
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 (*prepareDownlink) (GinBtree, Buffer);
|
||||||
void (*fillRoot) (GinBtree, Buffer, Buffer, Buffer);
|
void (*fillRoot) (GinBtree, Buffer, Buffer, Buffer);
|
||||||
|
|
||||||
bool isData;
|
bool isData;
|
||||||
@ -529,7 +530,6 @@ extern void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
|
|||||||
Datum key, GinNullCategory category,
|
Datum key, GinNullCategory category,
|
||||||
GinState *ginstate);
|
GinState *ginstate);
|
||||||
extern void ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
|
extern void ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
|
||||||
extern IndexTuple ginPageGetLinkItup(Buffer buf);
|
|
||||||
|
|
||||||
/* gindatapage.c */
|
/* gindatapage.c */
|
||||||
extern BlockNumber createPostingTree(Relation index,
|
extern BlockNumber createPostingTree(Relation index,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user