/* * Inserts array of item pointers, may execute several tree scan (very rare) */ void ginInsertItemPointers(GinPostingTreeScan *gdi, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats) { BlockNumber rootBlkno = gdi->stack->blkno; gdi->btree.items = items; gdi->btree.nitem = nitem; gdi->btree.curitem = 0; while (gdi->btree.curitem < gdi->btree.nitem) { if (!gdi->stack) gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno); gdi->stack = ginFindLeafPage(&gdi->btree, gdi->stack); if (gdi->btree.findItem(&(gdi->btree), gdi->stack)) { /* * gdi->btree.items[gdi->btree.curitem] already exists in index */ gdi->btree.curitem++; LockBuffer(gdi->stack->buffer, GIN_UNLOCK); freeGinBtreeStack(gdi->stack); } else ginInsertValue(&(gdi->btree), gdi->stack, buildStats); gdi->stack = NULL; } }
/* * Inserts array of item pointers, may execute several tree scan (very rare) */ void insertItemPointer(GinPostingTreeScan *gdi, ItemPointerData *items, uint32 nitem) { BlockNumber rootBlkno = gdi->stack->blkno; gdi->btree.items = items; gdi->btree.nitem = nitem; gdi->btree.curitem = 0; while (gdi->btree.curitem < gdi->btree.nitem) { if (!gdi->stack) gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno); gdi->stack = ginFindLeafPage(&gdi->btree, gdi->stack); if (gdi->btree.findItem(&(gdi->btree), gdi->stack)) elog(ERROR, "item pointer (%u,%d) already exists", ItemPointerGetBlockNumber(gdi->btree.items + gdi->btree.curitem), ItemPointerGetOffsetNumber(gdi->btree.items + gdi->btree.curitem)); ginInsertValue(&(gdi->btree), gdi->stack); gdi->stack = NULL; } }
GinPostingTreeScan * ginPrepareScanPostingTree(Relation index, BlockNumber rootBlkno, bool searchMode) { GinPostingTreeScan *gdi = (GinPostingTreeScan *) palloc0(sizeof(GinPostingTreeScan)); ginPrepareDataScan(&gdi->btree, index); gdi->btree.searchMode = searchMode; gdi->btree.fullScan = searchMode; gdi->stack = ginPrepareFindLeafPage(&gdi->btree, rootBlkno); return gdi; }
/* * Locates leaf page contained tuple */ GinBtreeStack * ginFindLeafPage(GinBtree btree, GinBtreeStack *stack) { bool isfirst = TRUE; BlockNumber rootBlkno; if (!stack) stack = ginPrepareFindLeafPage(btree, GIN_ROOT_BLKNO); rootBlkno = stack->blkno; for (;;) { Page page; BlockNumber child; int access = GIN_SHARE; stack->off = InvalidOffsetNumber; page = BufferGetPage(stack->buffer); if (isfirst) { if (GinPageIsLeaf(page) && !btree->searchMode) access = GIN_EXCLUSIVE; isfirst = FALSE; } else access = ginTraverseLock(stack->buffer, btree->searchMode); /* * ok, page is correctly locked, we should check to move right .., * root never has a right link, so small optimization */ while (btree->fullScan == FALSE && stack->blkno != rootBlkno && btree->isMoveRight(btree, page)) { BlockNumber rightlink = GinPageGetOpaque(page)->rightlink; if (rightlink == InvalidBlockNumber) /* rightmost page */ break; stack->blkno = rightlink; LockBuffer(stack->buffer, GIN_UNLOCK); stack->buffer = ReleaseAndReadBuffer(stack->buffer, btree->index, stack->blkno); LockBuffer(stack->buffer, access); page = BufferGetPage(stack->buffer); } if (GinPageIsLeaf(page)) /* we found, return locked page */ return stack; /* now we have correct buffer, try to find child */ child = btree->findChildPage(btree, stack); LockBuffer(stack->buffer, GIN_UNLOCK); Assert(child != InvalidBlockNumber); Assert(stack->blkno != child); if (btree->searchMode) { /* in search mode we may forget path to leaf */ stack->blkno = child; stack->buffer = ReleaseAndReadBuffer(stack->buffer, btree->index, stack->blkno); } else { GinBtreeStack *ptr = (GinBtreeStack *) palloc(sizeof(GinBtreeStack)); ptr->parent = stack; stack = ptr; stack->blkno = child; stack->buffer = ReadBuffer(btree->index, stack->blkno); stack->predictNumber = 1; } } /* keep compiler happy */ return NULL; }