LTP GCOV extension - code coverage report
Current view: directory - access/gin - gindatapage.c
Test: unnamed
Date: 2008-07-03 Instrumented lines: 286
Code covered: 45.1 % Executed lines: 129
Legend: not executed executed

       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * gindatapage.c
       4                 :  *        page utilities routines for the postgres inverted index access method.
       5                 :  *
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
       8                 :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *                      $PostgreSQL: pgsql/src/backend/access/gin/gindatapage.c,v 1.8 2007/11/15 21:14:31 momjian Exp $
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : 
      15                 : #include "postgres.h"
      16                 : #include "access/gin.h"
      17                 : 
      18                 : int
      19                 : compareItemPointers(ItemPointer a, ItemPointer b)
      20           37005 : {
      21           37005 :         if (GinItemPointerGetBlockNumber(a) == GinItemPointerGetBlockNumber(b))
      22                 :         {
      23           18569 :                 if (GinItemPointerGetOffsetNumber(a) == GinItemPointerGetOffsetNumber(b))
      24            2141 :                         return 0;
      25           16428 :                 return (GinItemPointerGetOffsetNumber(a) > GinItemPointerGetOffsetNumber(b)) ? 1 : -1;
      26                 :         }
      27                 : 
      28           18436 :         return (GinItemPointerGetBlockNumber(a) > GinItemPointerGetBlockNumber(b)) ? 1 : -1;
      29                 : }
      30                 : 
      31                 : /*
      32                 :  * Merge two ordered array of itempointer
      33                 :  */
      34                 : void
      35                 : MergeItemPointers(ItemPointerData *dst, ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb)
      36            1293 : {
      37            1293 :         ItemPointerData *dptr = dst;
      38            1293 :         ItemPointerData *aptr = a,
      39            1293 :                            *bptr = b;
      40                 : 
      41            3879 :         while (aptr - a < na && bptr - b < nb)
      42                 :         {
      43            1293 :                 if (compareItemPointers(aptr, bptr) > 0)
      44               0 :                         *dptr++ = *bptr++;
      45                 :                 else
      46            1293 :                         *dptr++ = *aptr++;
      47                 :         }
      48                 : 
      49            1293 :         while (aptr - a < na)
      50               0 :                 *dptr++ = *aptr++;
      51                 : 
      52           28033 :         while (bptr - b < nb)
      53           26740 :                 *dptr++ = *bptr++;
      54            1293 : }
      55                 : 
      56                 : /*
      57                 :  * Checks, should we move to right link...
      58                 :  * Compares inserting itemp pointer with right bound of current page
      59                 :  */
      60                 : static bool
      61                 : dataIsMoveRight(GinBtree btree, Page page)
      62               0 : {
      63               0 :         ItemPointer iptr = GinDataPageGetRightBound(page);
      64                 : 
      65               0 :         if (GinPageRightMost(page))
      66               0 :                 return FALSE;
      67                 : 
      68               0 :         return (compareItemPointers(btree->items + btree->curitem, iptr) > 0) ? TRUE : FALSE;
      69                 : }
      70                 : 
      71                 : /*
      72                 :  * Find correct PostingItem in non-leaf page. It supposed that page
      73                 :  * correctly chosen and searching value SHOULD be on page
      74                 :  */
      75                 : static BlockNumber
      76                 : dataLocateItem(GinBtree btree, GinBtreeStack *stack)
      77               0 : {
      78                 :         OffsetNumber low,
      79                 :                                 high,
      80                 :                                 maxoff;
      81               0 :         PostingItem *pitem = NULL;
      82                 :         int                     result;
      83               0 :         Page            page = BufferGetPage(stack->buffer);
      84                 : 
      85                 :         Assert(!GinPageIsLeaf(page));
      86                 :         Assert(GinPageIsData(page));
      87                 : 
      88               0 :         if (btree->fullScan)
      89                 :         {
      90               0 :                 stack->off = FirstOffsetNumber;
      91               0 :                 stack->predictNumber *= GinPageGetOpaque(page)->maxoff;
      92               0 :                 return btree->getLeftMostPage(btree, page);
      93                 :         }
      94                 : 
      95               0 :         low = FirstOffsetNumber;
      96               0 :         maxoff = high = GinPageGetOpaque(page)->maxoff;
      97                 :         Assert(high >= low);
      98                 : 
      99               0 :         high++;
     100                 : 
     101               0 :         while (high > low)
     102                 :         {
     103               0 :                 OffsetNumber mid = low + ((high - low) / 2);
     104                 : 
     105               0 :                 pitem = (PostingItem *) GinDataPageGetItem(page, mid);
     106                 : 
     107               0 :                 if (mid == maxoff)
     108                 : 
     109                 :                         /*
     110                 :                          * Right infinity, page already correctly chosen with a help of
     111                 :                          * dataIsMoveRight
     112                 :                          */
     113               0 :                         result = -1;
     114                 :                 else
     115                 :                 {
     116               0 :                         pitem = (PostingItem *) GinDataPageGetItem(page, mid);
     117               0 :                         result = compareItemPointers(btree->items + btree->curitem, &(pitem->key));
     118                 :                 }
     119                 : 
     120               0 :                 if (result == 0)
     121                 :                 {
     122               0 :                         stack->off = mid;
     123               0 :                         return PostingItemGetBlockNumber(pitem);
     124                 :                 }
     125               0 :                 else if (result > 0)
     126               0 :                         low = mid + 1;
     127                 :                 else
     128               0 :                         high = mid;
     129                 :         }
     130                 : 
     131                 :         Assert(high >= FirstOffsetNumber && high <= maxoff);
     132                 : 
     133               0 :         stack->off = high;
     134               0 :         pitem = (PostingItem *) GinDataPageGetItem(page, high);
     135               0 :         return PostingItemGetBlockNumber(pitem);
     136                 : }
     137                 : 
     138                 : /*
     139                 :  * Searches correct position for value on leaf page.
     140                 :  * Page should be correctly chosen.
     141                 :  * Returns true if value found on page.
     142                 :  */
     143                 : static bool
     144                 : dataLocateLeafItem(GinBtree btree, GinBtreeStack *stack)
     145              19 : {
     146              19 :         Page            page = BufferGetPage(stack->buffer);
     147                 :         OffsetNumber low,
     148                 :                                 high;
     149                 :         int                     result;
     150                 : 
     151                 :         Assert(GinPageIsLeaf(page));
     152                 :         Assert(GinPageIsData(page));
     153                 : 
     154              19 :         if (btree->fullScan)
     155                 :         {
     156               0 :                 stack->off = FirstOffsetNumber;
     157               0 :                 return TRUE;
     158                 :         }
     159                 : 
     160              19 :         low = FirstOffsetNumber;
     161              19 :         high = GinPageGetOpaque(page)->maxoff;
     162                 : 
     163              19 :         if (high < low)
     164                 :         {
     165               0 :                 stack->off = FirstOffsetNumber;
     166               0 :                 return false;
     167                 :         }
     168                 : 
     169              19 :         high++;
     170                 : 
     171              57 :         while (high > low)
     172                 :         {
     173              19 :                 OffsetNumber mid = low + ((high - low) / 2);
     174                 : 
     175              19 :                 result = compareItemPointers(btree->items + btree->curitem, (ItemPointer) GinDataPageGetItem(page, mid));
     176                 : 
     177              19 :                 if (result == 0)
     178                 :                 {
     179               0 :                         stack->off = mid;
     180               0 :                         return true;
     181                 :                 }
     182              19 :                 else if (result > 0)
     183              19 :                         low = mid + 1;
     184                 :                 else
     185               0 :                         high = mid;
     186                 :         }
     187                 : 
     188              19 :         stack->off = high;
     189              19 :         return false;
     190                 : }
     191                 : 
     192                 : /*
     193                 :  * Finds links to blkno on non-leaf page, returns
     194                 :  * offset of PostingItem
     195                 :  */
     196                 : static OffsetNumber
     197                 : dataFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber storedOff)
     198               0 : {
     199                 :         OffsetNumber i,
     200               0 :                                 maxoff = GinPageGetOpaque(page)->maxoff;
     201                 :         PostingItem *pitem;
     202                 : 
     203                 :         Assert(!GinPageIsLeaf(page));
     204                 :         Assert(GinPageIsData(page));
     205                 : 
     206                 :         /* if page isn't changed, we returns storedOff */
     207               0 :         if (storedOff >= FirstOffsetNumber && storedOff <= maxoff)
     208                 :         {
     209               0 :                 pitem = (PostingItem *) GinDataPageGetItem(page, storedOff);
     210               0 :                 if (PostingItemGetBlockNumber(pitem) == blkno)
     211               0 :                         return storedOff;
     212                 : 
     213                 :                 /*
     214                 :                  * we hope, that needed pointer goes to right. It's true if there
     215                 :                  * wasn't a deletion
     216                 :                  */
     217               0 :                 for (i = storedOff + 1; i <= maxoff; i++)
     218                 :                 {
     219               0 :                         pitem = (PostingItem *) GinDataPageGetItem(page, i);
     220               0 :                         if (PostingItemGetBlockNumber(pitem) == blkno)
     221               0 :                                 return i;
     222                 :                 }
     223                 : 
     224               0 :                 maxoff = storedOff - 1;
     225                 :         }
     226                 : 
     227                 :         /* last chance */
     228               0 :         for (i = FirstOffsetNumber; i <= maxoff; i++)
     229                 :         {
     230               0 :                 pitem = (PostingItem *) GinDataPageGetItem(page, i);
     231               0 :                 if (PostingItemGetBlockNumber(pitem) == blkno)
     232               0 :                         return i;
     233                 :         }
     234                 : 
     235               0 :         return InvalidOffsetNumber;
     236                 : }
     237                 : 
     238                 : /*
     239                 :  * returns blkno of leftmost child
     240                 :  */
     241                 : static BlockNumber
     242                 : dataGetLeftMostPage(GinBtree btree, Page page)
     243               0 : {
     244                 :         PostingItem *pitem;
     245                 : 
     246                 :         Assert(!GinPageIsLeaf(page));
     247                 :         Assert(GinPageIsData(page));
     248                 :         Assert(GinPageGetOpaque(page)->maxoff >= FirstOffsetNumber);
     249                 : 
     250               0 :         pitem = (PostingItem *) GinDataPageGetItem(page, FirstOffsetNumber);
     251               0 :         return PostingItemGetBlockNumber(pitem);
     252                 : }
     253                 : 
     254                 : /*
     255                 :  * add ItemPointer or PostingItem to page. data should point to
     256                 :  * correct value! depending on leaf or non-leaf page
     257                 :  */
     258                 : void
     259                 : GinDataPageAddItem(Page page, void *data, OffsetNumber offset)
     260            1730 : {
     261            1730 :         OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff;
     262                 :         char       *ptr;
     263                 : 
     264            1730 :         if (offset == InvalidOffsetNumber)
     265                 :         {
     266               0 :                 ptr = GinDataPageGetItem(page, maxoff + 1);
     267                 :         }
     268                 :         else
     269                 :         {
     270            1730 :                 ptr = GinDataPageGetItem(page, offset);
     271            1730 :                 if (maxoff + 1 - offset != 0)
     272               0 :                         memmove(ptr + GinSizeOfItem(page), ptr, (maxoff - offset + 1) * GinSizeOfItem(page));
     273                 :         }
     274            1730 :         memcpy(ptr, data, GinSizeOfItem(page));
     275                 : 
     276            1730 :         GinPageGetOpaque(page)->maxoff++;
     277            1730 : }
     278                 : 
     279                 : /*
     280                 :  * Deletes posting item from non-leaf page
     281                 :  */
     282                 : void
     283                 : PageDeletePostingItem(Page page, OffsetNumber offset)
     284               0 : {
     285               0 :         OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff;
     286                 : 
     287                 :         Assert(!GinPageIsLeaf(page));
     288                 :         Assert(offset >= FirstOffsetNumber && offset <= maxoff);
     289                 : 
     290               0 :         if (offset != maxoff)
     291               0 :                 memmove(GinDataPageGetItem(page, offset), GinDataPageGetItem(page, offset + 1),
     292                 :                                 sizeof(PostingItem) * (maxoff - offset));
     293                 : 
     294               0 :         GinPageGetOpaque(page)->maxoff--;
     295               0 : }
     296                 : 
     297                 : /*
     298                 :  * checks space to install new value,
     299                 :  * item pointer never deletes!
     300                 :  */
     301                 : static bool
     302                 : dataIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off)
     303              19 : {
     304              19 :         Page            page = BufferGetPage(buf);
     305                 : 
     306                 :         Assert(GinPageIsData(page));
     307                 :         Assert(!btree->isDelete);
     308                 : 
     309              19 :         if (GinPageIsLeaf(page))
     310                 :         {
     311              19 :                 if (GinPageRightMost(page) && off > GinPageGetOpaque(page)->maxoff)
     312                 :                 {
     313              19 :                         if ((btree->nitem - btree->curitem) * sizeof(ItemPointerData) <= GinDataPageGetFreeSpace(page))
     314              19 :                                 return true;
     315                 :                 }
     316               0 :                 else if (sizeof(ItemPointerData) <= GinDataPageGetFreeSpace(page))
     317               0 :                         return true;
     318                 :         }
     319               0 :         else if (sizeof(PostingItem) <= GinDataPageGetFreeSpace(page))
     320               0 :                 return true;
     321                 : 
     322               0 :         return false;
     323                 : }
     324                 : 
     325                 : /*
     326                 :  * In case of previous split update old child blkno to
     327                 :  * new right page
     328                 :  * item pointer never deletes!
     329                 :  */
     330                 : static BlockNumber
     331                 : dataPrepareData(GinBtree btree, Page page, OffsetNumber off)
     332              19 : {
     333              19 :         BlockNumber ret = InvalidBlockNumber;
     334                 : 
     335                 :         Assert(GinPageIsData(page));
     336                 : 
     337              19 :         if (!GinPageIsLeaf(page) && btree->rightblkno != InvalidBlockNumber)
     338                 :         {
     339               0 :                 PostingItem *pitem = (PostingItem *) GinDataPageGetItem(page, off);
     340                 : 
     341               0 :                 PostingItemSetBlockNumber(pitem, btree->rightblkno);
     342               0 :                 ret = btree->rightblkno;
     343                 :         }
     344                 : 
     345              19 :         btree->rightblkno = InvalidBlockNumber;
     346                 : 
     347              19 :         return ret;
     348                 : }
     349                 : 
     350                 : /*
     351                 :  * Places keys to page and fills WAL record. In case leaf page and
     352                 :  * build mode puts all ItemPointers to page.
     353                 :  */
     354                 : static void
     355                 : dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prdata)
     356              19 : {
     357              19 :         Page            page = BufferGetPage(buf);
     358                 :         static XLogRecData rdata[3];
     359              19 :         int                     sizeofitem = GinSizeOfItem(page);
     360                 :         static ginxlogInsert data;
     361              19 :         int                     cnt = 0;
     362                 : 
     363              19 :         *prdata = rdata;
     364                 :         Assert(GinPageIsData(page));
     365                 : 
     366              19 :         data.updateBlkno = dataPrepareData(btree, page, off);
     367                 : 
     368              19 :         data.node = btree->index->rd_node;
     369              19 :         data.blkno = BufferGetBlockNumber(buf);
     370              19 :         data.offset = off;
     371              19 :         data.nitem = 1;
     372              19 :         data.isDelete = FALSE;
     373              19 :         data.isData = TRUE;
     374              19 :         data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
     375                 : 
     376                 :         /*
     377                 :          * Prevent full page write if child's split occurs. That is needed to
     378                 :          * remove incomplete splits while replaying WAL
     379                 :          *
     380                 :          * data.updateBlkno contains new block number (of newly created right
     381                 :          * page) for recently splited page.
     382                 :          */
     383              19 :         if (data.updateBlkno == InvalidBlockNumber)
     384                 :         {
     385              19 :                 rdata[0].buffer = buf;
     386              19 :                 rdata[0].buffer_std = FALSE;
     387              19 :                 rdata[0].data = NULL;
     388              19 :                 rdata[0].len = 0;
     389              19 :                 rdata[0].next = &rdata[1];
     390              19 :                 cnt++;
     391                 :         }
     392                 : 
     393              19 :         rdata[cnt].buffer = InvalidBuffer;
     394              19 :         rdata[cnt].data = (char *) &data;
     395              19 :         rdata[cnt].len = sizeof(ginxlogInsert);
     396              19 :         rdata[cnt].next = &rdata[cnt + 1];
     397              19 :         cnt++;
     398                 : 
     399              19 :         rdata[cnt].buffer = InvalidBuffer;
     400              19 :         rdata[cnt].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
     401              19 :         rdata[cnt].len = sizeofitem;
     402              19 :         rdata[cnt].next = NULL;
     403                 : 
     404              19 :         if (GinPageIsLeaf(page))
     405                 :         {
     406              38 :                 if (GinPageRightMost(page) && off > GinPageGetOpaque(page)->maxoff)
     407                 :                 {
     408                 :                         /* usually, create index... */
     409              19 :                         uint32          savedPos = btree->curitem;
     410                 : 
     411            1768 :                         while (btree->curitem < btree->nitem)
     412                 :                         {
     413            1730 :                                 GinDataPageAddItem(page, btree->items + btree->curitem, off);
     414            1730 :                                 off++;
     415            1730 :                                 btree->curitem++;
     416                 :                         }
     417              19 :                         data.nitem = btree->curitem - savedPos;
     418              19 :                         rdata[cnt].len = sizeofitem * data.nitem;
     419                 :                 }
     420                 :                 else
     421                 :                 {
     422               0 :                         GinDataPageAddItem(page, btree->items + btree->curitem, off);
     423               0 :                         btree->curitem++;
     424                 :                 }
     425                 :         }
     426                 :         else
     427               0 :                 GinDataPageAddItem(page, &(btree->pitem), off);
     428              19 : }
     429                 : 
     430                 : /*
     431                 :  * split page and fills WAL record. original buffer(lbuf) leaves untouched,
     432                 :  * returns shadow page of lbuf filled new data. In leaf page and build mode puts all
     433                 :  * ItemPointers to pages. Also, in build mode splits data by way to full fulled
     434                 :  * left page
     435                 :  */
     436                 : static Page
     437                 : dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRecData **prdata)
     438               0 : {
     439                 :         static ginxlogSplit data;
     440                 :         static XLogRecData rdata[4];
     441                 :         static char vector[2 * BLCKSZ];
     442                 :         char       *ptr;
     443                 :         OffsetNumber separator;
     444                 :         ItemPointer bound;
     445               0 :         Page            lpage = GinPageGetCopyPage(BufferGetPage(lbuf));
     446               0 :         ItemPointerData oldbound = *GinDataPageGetRightBound(lpage);
     447               0 :         int                     sizeofitem = GinSizeOfItem(lpage);
     448               0 :         OffsetNumber maxoff = GinPageGetOpaque(lpage)->maxoff;
     449               0 :         Page            rpage = BufferGetPage(rbuf);
     450               0 :         Size            pageSize = PageGetPageSize(lpage);
     451                 :         Size            freeSpace;
     452               0 :         uint32          nCopied = 1;
     453                 : 
     454               0 :         GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
     455               0 :         freeSpace = GinDataPageGetFreeSpace(rpage);
     456                 : 
     457               0 :         *prdata = rdata;
     458               0 :         data.leftChildBlkno = (GinPageIsLeaf(lpage)) ?
     459                 :                 InvalidOffsetNumber : PostingItemGetBlockNumber(&(btree->pitem));
     460               0 :         data.updateBlkno = dataPrepareData(btree, lpage, off);
     461                 : 
     462               0 :         memcpy(vector, GinDataPageGetItem(lpage, FirstOffsetNumber),
     463                 :                    maxoff * sizeofitem);
     464                 : 
     465               0 :         if (GinPageIsLeaf(lpage) && GinPageRightMost(lpage) && off > GinPageGetOpaque(lpage)->maxoff)
     466                 :         {
     467               0 :                 nCopied = 0;
     468               0 :                 while (btree->curitem < btree->nitem && maxoff * sizeof(ItemPointerData) < 2 * (freeSpace - sizeof(ItemPointerData)))
     469                 :                 {
     470               0 :                         memcpy(vector + maxoff * sizeof(ItemPointerData), btree->items + btree->curitem,
     471                 :                                    sizeof(ItemPointerData));
     472               0 :                         maxoff++;
     473               0 :                         nCopied++;
     474               0 :                         btree->curitem++;
     475                 :                 }
     476                 :         }
     477                 :         else
     478                 :         {
     479               0 :                 ptr = vector + (off - 1) * sizeofitem;
     480               0 :                 if (maxoff + 1 - off != 0)
     481               0 :                         memmove(ptr + sizeofitem, ptr, (maxoff - off + 1) * sizeofitem);
     482               0 :                 if (GinPageIsLeaf(lpage))
     483                 :                 {
     484               0 :                         memcpy(ptr, btree->items + btree->curitem, sizeofitem);
     485               0 :                         btree->curitem++;
     486                 :                 }
     487                 :                 else
     488               0 :                         memcpy(ptr, &(btree->pitem), sizeofitem);
     489                 : 
     490               0 :                 maxoff++;
     491                 :         }
     492                 : 
     493                 :         /*
     494                 :          * we suppose that during index creation table scaned from begin to end,
     495                 :          * so ItemPointers are monotonically increased..
     496                 :          */
     497               0 :         if (btree->isBuild && GinPageRightMost(lpage))
     498               0 :                 separator = freeSpace / sizeofitem;
     499                 :         else
     500               0 :                 separator = maxoff / 2;
     501                 : 
     502               0 :         GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
     503               0 :         GinInitPage(lpage, GinPageGetOpaque(rpage)->flags, pageSize);
     504                 : 
     505               0 :         memcpy(GinDataPageGetItem(lpage, FirstOffsetNumber), vector, separator * sizeofitem);
     506               0 :         GinPageGetOpaque(lpage)->maxoff = separator;
     507               0 :         memcpy(GinDataPageGetItem(rpage, FirstOffsetNumber),
     508                 :                  vector + separator * sizeofitem, (maxoff - separator) * sizeofitem);
     509               0 :         GinPageGetOpaque(rpage)->maxoff = maxoff - separator;
     510                 : 
     511               0 :         PostingItemSetBlockNumber(&(btree->pitem), BufferGetBlockNumber(lbuf));
     512               0 :         if (GinPageIsLeaf(lpage))
     513               0 :                 btree->pitem.key = *(ItemPointerData *) GinDataPageGetItem(lpage,
     514                 :                                                                                         GinPageGetOpaque(lpage)->maxoff);
     515                 :         else
     516               0 :                 btree->pitem.key = ((PostingItem *) GinDataPageGetItem(lpage,
     517                 :                                                                           GinPageGetOpaque(lpage)->maxoff))->key;
     518               0 :         btree->rightblkno = BufferGetBlockNumber(rbuf);
     519                 : 
     520                 :         /* set up right bound for left page */
     521               0 :         bound = GinDataPageGetRightBound(lpage);
     522               0 :         *bound = btree->pitem.key;
     523                 : 
     524                 :         /* set up right bound for right page */
     525               0 :         bound = GinDataPageGetRightBound(rpage);
     526               0 :         *bound = oldbound;
     527                 : 
     528               0 :         data.node = btree->index->rd_node;
     529               0 :         data.rootBlkno = InvalidBlockNumber;
     530               0 :         data.lblkno = BufferGetBlockNumber(lbuf);
     531               0 :         data.rblkno = BufferGetBlockNumber(rbuf);
     532               0 :         data.separator = separator;
     533               0 :         data.nitem = maxoff;
     534               0 :         data.isData = TRUE;
     535               0 :         data.isLeaf = GinPageIsLeaf(lpage) ? TRUE : FALSE;
     536               0 :         data.isRootSplit = FALSE;
     537               0 :         data.rightbound = oldbound;
     538                 : 
     539               0 :         rdata[0].buffer = InvalidBuffer;
     540               0 :         rdata[0].data = (char *) &data;
     541               0 :         rdata[0].len = sizeof(ginxlogSplit);
     542               0 :         rdata[0].next = &rdata[1];
     543                 : 
     544               0 :         rdata[1].buffer = InvalidBuffer;
     545               0 :         rdata[1].data = vector;
     546               0 :         rdata[1].len = MAXALIGN(maxoff * sizeofitem);
     547               0 :         rdata[1].next = NULL;
     548                 : 
     549               0 :         return lpage;
     550                 : }
     551                 : 
     552                 : /*
     553                 :  * Fills new root by right bound values from child.
     554                 :  * Also called from ginxlog, should not use btree
     555                 :  */
     556                 : void
     557                 : dataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf)
     558               0 : {
     559               0 :         Page            page = BufferGetPage(root),
     560               0 :                                 lpage = BufferGetPage(lbuf),
     561               0 :                                 rpage = BufferGetPage(rbuf);
     562                 :         PostingItem li,
     563                 :                                 ri;
     564                 : 
     565               0 :         li.key = *GinDataPageGetRightBound(lpage);
     566               0 :         PostingItemSetBlockNumber(&li, BufferGetBlockNumber(lbuf));
     567               0 :         GinDataPageAddItem(page, &li, InvalidOffsetNumber);
     568                 : 
     569               0 :         ri.key = *GinDataPageGetRightBound(rpage);
     570               0 :         PostingItemSetBlockNumber(&ri, BufferGetBlockNumber(rbuf));
     571               0 :         GinDataPageAddItem(page, &ri, InvalidOffsetNumber);
     572               0 : }
     573                 : 
     574                 : void
     575                 : prepareDataScan(GinBtree btree, Relation index)
     576              23 : {
     577              23 :         memset(btree, 0, sizeof(GinBtreeData));
     578              23 :         btree->index = index;
     579              23 :         btree->isMoveRight = dataIsMoveRight;
     580              23 :         btree->findChildPage = dataLocateItem;
     581              23 :         btree->findItem = dataLocateLeafItem;
     582              23 :         btree->findChildPtr = dataFindChildPtr;
     583              23 :         btree->getLeftMostPage = dataGetLeftMostPage;
     584              23 :         btree->isEnoughSpace = dataIsEnoughSpace;
     585              23 :         btree->placeToPage = dataPlaceToPage;
     586              23 :         btree->splitPage = dataSplitPage;
     587              23 :         btree->fillRoot = dataFillRoot;
     588                 : 
     589              23 :         btree->searchMode = FALSE;
     590              23 :         btree->isDelete = FALSE;
     591              23 :         btree->fullScan = FALSE;
     592              23 :         btree->isBuild = FALSE;
     593              23 : }
     594                 : 
     595                 : GinPostingTreeScan *
     596                 : prepareScanPostingTree(Relation index, BlockNumber rootBlkno, bool searchMode)
     597              23 : {
     598              23 :         GinPostingTreeScan *gdi = (GinPostingTreeScan *) palloc0(sizeof(GinPostingTreeScan));
     599                 : 
     600              23 :         prepareDataScan(&gdi->btree, index);
     601                 : 
     602              23 :         gdi->btree.searchMode = searchMode;
     603              23 :         gdi->btree.fullScan = searchMode;
     604                 : 
     605              23 :         gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno);
     606                 : 
     607              23 :         return gdi;
     608                 : }
     609                 : 
     610                 : /*
     611                 :  * Inserts array of item pointers, may execute several tree scan (very rare)
     612                 :  */
     613                 : void
     614                 : insertItemPointer(GinPostingTreeScan *gdi, ItemPointerData *items, uint32 nitem)
     615              19 : {
     616              19 :         BlockNumber rootBlkno = gdi->stack->blkno;
     617                 : 
     618              19 :         gdi->btree.items = items;
     619              19 :         gdi->btree.nitem = nitem;
     620              19 :         gdi->btree.curitem = 0;
     621                 : 
     622              57 :         while (gdi->btree.curitem < gdi->btree.nitem)
     623                 :         {
     624              19 :                 if (!gdi->stack)
     625               0 :                         gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno);
     626                 : 
     627              19 :                 gdi->stack = ginFindLeafPage(&gdi->btree, gdi->stack);
     628                 : 
     629              19 :                 if (gdi->btree.findItem(&(gdi->btree), gdi->stack))
     630               0 :                         elog(ERROR, "item pointer (%u,%d) already exists",
     631                 :                         ItemPointerGetBlockNumber(gdi->btree.items + gdi->btree.curitem),
     632                 :                                  ItemPointerGetOffsetNumber(gdi->btree.items + gdi->btree.curitem));
     633                 : 
     634              19 :                 ginInsertValue(&(gdi->btree), gdi->stack);
     635                 : 
     636              19 :                 gdi->stack = NULL;
     637                 :         }
     638              19 : }
     639                 : 
     640                 : Buffer
     641                 : scanBeginPostingTree(GinPostingTreeScan *gdi)
     642               4 : {
     643               4 :         gdi->stack = ginFindLeafPage(&gdi->btree, gdi->stack);
     644               4 :         return gdi->stack->buffer;
     645                 : }

Generated by: LTP GCOV extension version 1.5