Refactor the internal GIN B-tree interface for forming a downlink.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 20 Nov 2013 14:57:41 +0000 (16:57 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 20 Nov 2013 14:57:41 +0000 (16:57 +0200)
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.

src/backend/access/gin/ginbtree.c
src/backend/access/gin/gindatapage.c
src/backend/access/gin/ginentrypage.c
src/backend/access/gin/ginxlog.c
src/include/access/gin_private.h

index 0d93c52e04326fdb1521a05f36d00fa3b06d9aaf..c4801d5cd8937fbb3977733ab756427e5b5fe847 100644 (file)
@@ -452,6 +452,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
            }
        }
 
+       btree->prepareDownlink(btree, stack->buffer);
        btree->isDelete = FALSE;
 
        /* search parent to lock */
index 67d748bd7112bf2bad04771407579f27f9c55fc0..fbdde1dc02437b4a18b8cc0d5176b7204b553888 100644 (file)
@@ -580,12 +580,20 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe
    rdata[1].len = MAXALIGN(maxoff * sizeofitem);
    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));
    btree->pitem.key = *GinDataPageGetRightBound(lpage);
-   btree->rightblkno = BufferGetBlockNumber(rbuf);
-
-   return lpage;
+   btree->rightblkno = GinPageGetOpaque(lpage)->rightlink;
 }
 
 /*
@@ -704,6 +712,7 @@ ginPrepareDataScan(GinBtree btree, Relation index)
    btree->placeToPage = dataPlaceToPage;
    btree->splitPage = dataSplitPage;
    btree->fillRoot = ginDataFillRoot;
+   btree->prepareDownlink = dataPrepareDownlink;
 
    btree->isData = TRUE;
    btree->isDelete = FALSE;
index a22fd32d9dab502f307719f7bc36460aa3e39e35..ec0114e7d39da2d12dbb9320a8e5f68ca6882673 100644 (file)
@@ -570,8 +570,7 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
    Size        lsize = 0,
                size;
    char       *ptr;
-   IndexTuple  itup,
-               leftrightmost = NULL;
+   IndexTuple  itup;
    Page        page;
    Page        lpage = PageGetTempPageCopy(BufferGetPage(lbuf));
    Page        rpage = BufferGetPage(rbuf);
@@ -635,7 +634,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
        }
        else
        {
-           leftrightmost = itup;
            lsize += MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
        }
 
@@ -645,11 +643,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
        ptr += MAXALIGN(IndexTupleSize(itup));
    }
 
-   btree->entry = GinFormInteriorTuple(leftrightmost, lpage,
-                                       BufferGetBlockNumber(lbuf));
-
-   btree->rightblkno = BufferGetBlockNumber(rbuf);
-
    data.node = btree->index->rd_node;
    data.rootBlkno = InvalidBlockNumber;
    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
-ginPageGetLinkItup(Buffer buf)
+static void
+entryPrepareDownlink(GinBtree btree, Buffer lbuf)
 {
-   IndexTuple  itup,
-               nitup;
-   Page        page = BufferGetPage(buf);
+   Page        lpage = BufferGetPage(lbuf);
+   IndexTuple  itup;
 
-   itup = getRightMostTuple(page);
-   nitup = GinFormInteriorTuple(itup, page, BufferGetBlockNumber(buf));
+   itup = getRightMostTuple(lpage);
 
-   return nitup;
+   btree->entry = GinFormInteriorTuple(itup,
+                                       lpage,
+                                       BufferGetBlockNumber(lbuf));
+   btree->rightblkno = GinPageGetOpaque(lpage)->rightlink;
 }
 
 /*
@@ -696,17 +690,21 @@ ginPageGetLinkItup(Buffer buf)
 void
 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;
 
-   page = BufferGetPage(root);
-
-   itup = ginPageGetLinkItup(lbuf);
+   itup = GinFormInteriorTuple(getRightMostTuple(lpage),
+                               lpage,
+                               BufferGetBlockNumber(lbuf));
    if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
        elog(ERROR, "failed to add item to index root page");
    pfree(itup);
 
-   itup = ginPageGetLinkItup(rbuf);
+   itup = GinFormInteriorTuple(getRightMostTuple(rpage),
+                               rpage,
+                               BufferGetBlockNumber(rbuf));
    if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
        elog(ERROR, "failed to add item to index root page");
    pfree(itup);
@@ -736,6 +734,7 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
    btree->placeToPage = entryPlaceToPage;
    btree->splitPage = entrySplitPage;
    btree->fillRoot = ginEntryFillRoot;
+   btree->prepareDownlink = entryPrepareDownlink;
 
    btree->isData = FALSE;
    btree->fullScan = FALSE;
index 4d0ccb876f21f5971c2940e772ce9ffb9645f5f1..ddac34306131ef7f464f37d039233b02e45a6009 100644 (file)
@@ -799,31 +799,20 @@ ginContinueSplit(ginIncompleteSplit *split)
        ginPrepareEntryScan(&btree,
                            InvalidOffsetNumber, (Datum) 0, GIN_CAT_NULL_KEY,
                            &ginstate);
-       btree.entry = ginPageGetLinkItup(buffer);
    }
    else
    {
-       Page        page = BufferGetPage(buffer);
-
        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.buffer = buffer;
    stack.off = InvalidOffsetNumber;
    stack.parent = NULL;
 
    ginFindParents(&btree, &stack, split->rootBlkno);
+
+   btree.prepareDownlink(&btree, buffer);
    ginInsertValue(&btree, stack.parent, NULL);
 
    FreeFakeRelcacheEntry(reln);
index 7491d7cf0ca67c59ae8699552096e5280726a696..39529353d17b472c23adebc0f354bcf5ee1ac408 100644 (file)
@@ -487,6 +487,7 @@ typedef struct GinBtreeData
    OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
    bool        (*placeToPage) (GinBtree, Buffer, OffsetNumber, XLogRecData **);
    Page        (*splitPage) (GinBtree, Buffer, Buffer, OffsetNumber, XLogRecData **);
+   void        (*prepareDownlink) (GinBtree, Buffer);
    void        (*fillRoot) (GinBtree, Buffer, Buffer, Buffer);
 
    bool        isData;
@@ -529,7 +530,6 @@ extern void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
                    Datum key, GinNullCategory category,
                    GinState *ginstate);
 extern void ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
-extern IndexTuple ginPageGetLinkItup(Buffer buf);
 
 /* gindatapage.c */
 extern BlockNumber createPostingTree(Relation index,