diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2013-11-27 15:43:05 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2013-11-27 15:43:05 +0200 |
commit | ce5326eed386959aac7a322880896ddeade7fd52 (patch) | |
tree | 16f903bb47df48ab748c485c7e350e5dced2c253 /src/backend/access/gin/ginentrypage.c | |
parent | 4118f7e8ede8a3616189b53983aea293fd0b3cb1 (diff) |
More GIN refactoring.
Separate the insertion payload from the more static portions of GinBtree.
GinBtree now only contains information related to searching the tree, and
the information of what to insert is passed separately.
Add root block number to GinBtree, instead of passing it around all the
functions as argument.
Split off ginFinishSplit() from ginInsertValue(). ginFinishSplit is
responsible for finding the parent and inserting the downlink to it.
Diffstat (limited to 'src/backend/access/gin/ginentrypage.c')
-rw-r--r-- | src/backend/access/gin/ginentrypage.c | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index ec0114e7d39..1949f24b977 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -112,6 +112,7 @@ GinFormTuple(GinState *ginstate, if (newsize != IndexTupleSize(itup)) { itup = repalloc(itup, newsize); + /* * PostgreSQL 9.3 and earlier did not clear this new space, so we * might find uninitialized padding when reading tuples from disk. @@ -431,22 +432,26 @@ entryGetLeftMostPage(GinBtree btree, Page page) } static bool -entryIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off) +entryIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off, + GinBtreeEntryInsertData *insertData) { - Size itupsz = 0; + Size releasedsz = 0; + Size addedsz; Page page = BufferGetPage(buf); - Assert(btree->entry); + Assert(insertData->entry); Assert(!GinPageIsData(page)); - if (btree->isDelete) + if (insertData->isDelete) { IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off)); - itupsz = MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData); + releasedsz = MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData); } - if (PageGetFreeSpace(page) + itupsz >= MAXALIGN(IndexTupleSize(btree->entry)) + sizeof(ItemIdData)) + addedsz = MAXALIGN(IndexTupleSize(insertData->entry)) + sizeof(ItemIdData); + + if (PageGetFreeSpace(page) + releasedsz >= addedsz) return true; return false; @@ -457,42 +462,42 @@ entryIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off) * should update it, update old child blkno to new right page * if child split occurred */ -static BlockNumber -entryPreparePage(GinBtree btree, Page page, OffsetNumber off) +static void +entryPreparePage(GinBtree btree, Page page, OffsetNumber off, + GinBtreeEntryInsertData *insertData, BlockNumber updateblkno) { - BlockNumber ret = InvalidBlockNumber; - - Assert(btree->entry); + Assert(insertData->entry); Assert(!GinPageIsData(page)); - if (btree->isDelete) + if (insertData->isDelete) { Assert(GinPageIsLeaf(page)); PageIndexTupleDelete(page, off); } - if (!GinPageIsLeaf(page) && btree->rightblkno != InvalidBlockNumber) + if (!GinPageIsLeaf(page) && updateblkno != InvalidBlockNumber) { IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off)); - GinSetDownlink(itup, btree->rightblkno); - ret = btree->rightblkno; + GinSetDownlink(itup, updateblkno); } - - btree->rightblkno = InvalidBlockNumber; - - return ret; } /* * Place tuple on page and fills WAL record * * If the tuple doesn't fit, returns false without modifying the page. + * + * On insertion to an internal node, in addition to inserting the given item, + * the downlink of the existing item at 'off' is updated to point to + * 'updateblkno'. */ static bool entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, + void *insertPayload, BlockNumber updateblkno, XLogRecData **prdata) { + GinBtreeEntryInsertData *insertData = insertPayload; Page page = BufferGetPage(buf); OffsetNumber placed; int cnt = 0; @@ -502,13 +507,17 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, static ginxlogInsert data; /* quick exit if it doesn't fit */ - if (!entryIsEnoughSpace(btree, buf, off)) + if (!entryIsEnoughSpace(btree, buf, off, insertData)) return false; *prdata = rdata; - data.updateBlkno = entryPreparePage(btree, page, off); + entryPreparePage(btree, page, off, insertData, updateblkno); + data.updateBlkno = updateblkno; - placed = PageAddItem(page, (Item) btree->entry, IndexTupleSize(btree->entry), off, false, false); + placed = PageAddItem(page, + (Item) insertData->entry, + IndexTupleSize(insertData->entry), + off, false, false); if (placed != off) elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(btree->index)); @@ -517,7 +526,7 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, data.blkno = BufferGetBlockNumber(buf); data.offset = off; data.nitem = 1; - data.isDelete = btree->isDelete; + data.isDelete = insertData->isDelete; data.isData = false; data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE; @@ -545,12 +554,10 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, cnt++; rdata[cnt].buffer = InvalidBuffer; - rdata[cnt].data = (char *) btree->entry; - rdata[cnt].len = IndexTupleSize(btree->entry); + rdata[cnt].data = (char *) insertData->entry; + rdata[cnt].len = IndexTupleSize(insertData->entry); rdata[cnt].next = NULL; - btree->entry = NULL; - return true; } @@ -561,8 +568,11 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, * an equal number! */ static Page -entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRecData **prdata) +entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, + void *insertPayload, + BlockNumber updateblkno, XLogRecData **prdata) { + GinBtreeEntryInsertData *insertData = insertPayload; OffsetNumber i, maxoff, separator = InvalidOffsetNumber; @@ -583,8 +593,9 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR *prdata = rdata; data.leftChildBlkno = (GinPageIsLeaf(lpage)) ? - InvalidOffsetNumber : GinGetDownlink(btree->entry); - data.updateBlkno = entryPreparePage(btree, lpage, off); + InvalidOffsetNumber : GinGetDownlink(insertData->entry); + data.updateBlkno = updateblkno; + entryPreparePage(btree, lpage, off, insertData, updateblkno); maxoff = PageGetMaxOffsetNumber(lpage); ptr = tupstore; @@ -593,8 +604,8 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR { if (i == off) { - size = MAXALIGN(IndexTupleSize(btree->entry)); - memcpy(ptr, btree->entry, size); + size = MAXALIGN(IndexTupleSize(insertData->entry)); + memcpy(ptr, insertData->entry, size); ptr += size; totalsize += size + sizeof(ItemIdData); } @@ -608,8 +619,8 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR if (off == maxoff + 1) { - size = MAXALIGN(IndexTupleSize(btree->entry)); - memcpy(ptr, btree->entry, size); + size = MAXALIGN(IndexTupleSize(insertData->entry)); + memcpy(ptr, insertData->entry, size); ptr += size; totalsize += size + sizeof(ItemIdData); } @@ -667,20 +678,23 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR } /* - * Prepare the state in 'btree' for inserting a downlink for given buffer. + * Construct insertion payload for inserting the downlink for given buffer. */ -static void +static void * entryPrepareDownlink(GinBtree btree, Buffer lbuf) { + GinBtreeEntryInsertData *insertData; Page lpage = BufferGetPage(lbuf); + BlockNumber lblkno = BufferGetBlockNumber(lbuf); IndexTuple itup; itup = getRightMostTuple(lpage); - btree->entry = GinFormInteriorTuple(itup, - lpage, - BufferGetBlockNumber(lbuf)); - btree->rightblkno = GinPageGetOpaque(lpage)->rightlink; + insertData = palloc(sizeof(GinBtreeEntryInsertData)); + insertData->entry = GinFormInteriorTuple(itup, lpage, lblkno); + insertData->isDelete = false; + + return insertData; } /* @@ -724,6 +738,7 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, memset(btree, 0, sizeof(GinBtreeData)); btree->index = ginstate->index; + btree->rootBlkno = GIN_ROOT_BLKNO; btree->ginstate = ginstate; btree->findChildPage = entryLocateEntry; @@ -743,5 +758,4 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, btree->entryAttnum = attnum; btree->entryKey = key; btree->entryCategory = category; - btree->isDelete = FALSE; } |