예제 #1
0
/*
 * Fills new root by right bound values from child.
 * Also called from ginxlog, should not use btree
 */
void
ginDataFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage)
{
	PostingItem li,
				ri;

	li.key = *GinDataPageGetRightBound(lpage);
	PostingItemSetBlockNumber(&li, lblkno);
	GinDataPageAddPostingItem(root, &li, InvalidOffsetNumber);

	ri.key = *GinDataPageGetRightBound(rpage);
	PostingItemSetBlockNumber(&ri, rblkno);
	GinDataPageAddPostingItem(root, &ri, InvalidOffsetNumber);
}
예제 #2
0
static void
ginRedoInsertData(Buffer buffer, bool isLeaf, BlockNumber rightblkno, void *rdata)
{
	Page		page = BufferGetPage(buffer);

	if (isLeaf)
	{
		ginxlogRecompressDataLeaf *data = (ginxlogRecompressDataLeaf *) rdata;

		Assert(GinPageIsLeaf(page));

		ginRedoRecompress(page, data);
	}
	else
	{
		ginxlogInsertDataInternal *data = (ginxlogInsertDataInternal *) rdata;
		PostingItem *oldpitem;

		Assert(!GinPageIsLeaf(page));

		/* update link to right page after split */
		oldpitem = GinDataPageGetPostingItem(page, data->offset);
		PostingItemSetBlockNumber(oldpitem, rightblkno);

		GinDataPageAddPostingItem(page, &data->newitem, data->offset);
	}
}
예제 #3
0
/*
 * Fills new root by right bound values from child.
 * Also called from ginxlog, should not use btree
 */
void
ginDataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf)
{
	Page		page = BufferGetPage(root),
				lpage = BufferGetPage(lbuf),
				rpage = BufferGetPage(rbuf);
	PostingItem li,
				ri;

	li.key = *GinDataPageGetRightBound(lpage);
	PostingItemSetBlockNumber(&li, BufferGetBlockNumber(lbuf));
	GinDataPageAddPostingItem(page, &li, InvalidOffsetNumber);

	ri.key = *GinDataPageGetRightBound(rpage);
	PostingItemSetBlockNumber(&ri, BufferGetBlockNumber(rbuf));
	GinDataPageAddPostingItem(page, &ri, InvalidOffsetNumber);
}
예제 #4
0
static void
ginRedoSplitData(Page lpage, Page rpage, void *rdata)
{
    bool		isleaf = GinPageIsLeaf(lpage);

    if (isleaf)
    {
        ginxlogSplitDataLeaf *data = (ginxlogSplitDataLeaf *) rdata;
        Pointer		lptr = (Pointer) rdata + sizeof(ginxlogSplitDataLeaf);
        Pointer		rptr = lptr + data->lsize;

        Assert(data->lsize > 0 && data->lsize <= GinDataPageMaxDataSize);
        Assert(data->rsize > 0 && data->rsize <= GinDataPageMaxDataSize);

        memcpy(GinDataLeafPageGetPostingList(lpage), lptr, data->lsize);
        memcpy(GinDataLeafPageGetPostingList(rpage), rptr, data->rsize);

        GinDataPageSetDataSize(lpage, data->lsize);
        GinDataPageSetDataSize(rpage, data->rsize);
        *GinDataPageGetRightBound(lpage) = data->lrightbound;
        *GinDataPageGetRightBound(rpage) = data->rrightbound;
    }
    else
    {
        ginxlogSplitDataInternal *data = (ginxlogSplitDataInternal *) rdata;
        PostingItem *items = (PostingItem *) ((char *) rdata + sizeof(ginxlogSplitDataInternal));
        OffsetNumber i;
        OffsetNumber maxoff;

        for (i = 0; i < data->separator; i++)
            GinDataPageAddPostingItem(lpage, &items[i], InvalidOffsetNumber);
        for (i = data->separator; i < data->nitem; i++)
            GinDataPageAddPostingItem(rpage, &items[i], InvalidOffsetNumber);

        /* set up right key */
        maxoff = GinPageGetOpaque(lpage)->maxoff;
        *GinDataPageGetRightBound(lpage) = GinDataPageGetPostingItem(lpage, maxoff)->key;
        *GinDataPageGetRightBound(rpage) = data->rightbound;
    }
}
예제 #5
0
/*
 * Places keys to page and fills WAL record. In case leaf page and
 * build mode puts all ItemPointers to page.
 *
 * If none of the keys 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
dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off,
				void *insertdata, BlockNumber updateblkno,
				XLogRecData **prdata)
{
	Page		page = BufferGetPage(buf);
	/* these must be static so they can be returned to caller */
	static XLogRecData rdata[2];

	/* quick exit if it doesn't fit */
	if (!dataIsEnoughSpace(btree, buf, off, insertdata))
		return false;

	*prdata = rdata;
	Assert(GinPageIsData(page));

	/* Update existing downlink to point to next page (on internal page) */
	if (!GinPageIsLeaf(page))
	{
		PostingItem *pitem = GinDataPageGetPostingItem(page, off);

		PostingItemSetBlockNumber(pitem, updateblkno);
	}

	if (GinPageIsLeaf(page))
	{
		GinBtreeDataLeafInsertData *items = insertdata;
		static ginxlogInsertDataLeaf data;
		uint32		savedPos = items->curitem;

		if (GinPageRightMost(page) && off > GinPageGetOpaque(page)->maxoff)
		{
			/* usually, create index... */
			while (items->curitem < items->nitem)
			{
				GinDataPageAddItemPointer(page, items->items + items->curitem, off);
				off++;
				items->curitem++;
			}
			data.nitem = items->curitem - savedPos;
		}
		else
		{
			GinDataPageAddItemPointer(page, items->items + items->curitem, off);
			items->curitem++;
			data.nitem = 1;
		}

		rdata[0].buffer = buf;
		rdata[0].buffer_std = false;
		rdata[0].data = (char *) &data;
		rdata[0].len = offsetof(ginxlogInsertDataLeaf, items);
		rdata[0].next = &rdata[1];

		rdata[1].buffer = buf;
		rdata[1].buffer_std = false;
		rdata[1].data = (char *) &items->items[savedPos];
		rdata[1].len = sizeof(ItemPointerData) * data.nitem;
		rdata[1].next = NULL;
	}
	else
	{
		PostingItem *pitem = insertdata;

		GinDataPageAddPostingItem(page, pitem, off);

		rdata[0].buffer = buf;
		rdata[0].buffer_std = false;
		rdata[0].data = (char *) pitem;
		rdata[0].len = sizeof(PostingItem);
		rdata[0].next = NULL;
	}

	return true;
}
예제 #6
0
/*
 * Places keys to page and fills WAL record. In case leaf page and
 * build mode puts all ItemPointers to page.
 */
static void
dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prdata)
{
	Page		page = BufferGetPage(buf);
	int			sizeofitem = GinSizeOfDataPageItem(page);
	int			cnt = 0;

	/* these must be static so they can be returned to caller */
	static XLogRecData rdata[3];
	static ginxlogInsert data;

	*prdata = rdata;
	Assert(GinPageIsData(page));

	data.updateBlkno = dataPrepareData(btree, page, off);

	data.node = btree->index->rd_node;
	data.blkno = BufferGetBlockNumber(buf);
	data.offset = off;
	data.nitem = 1;
	data.isDelete = FALSE;
	data.isData = TRUE;
	data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;

	/*
	 * Prevent full page write if child's split occurs. That is needed to
	 * remove incomplete splits while replaying WAL
	 *
	 * data.updateBlkno contains new block number (of newly created right
	 * page) for recently splited page.
	 */
	if (data.updateBlkno == InvalidBlockNumber)
	{
		rdata[0].buffer = buf;
		rdata[0].buffer_std = FALSE;
		rdata[0].data = NULL;
		rdata[0].len = 0;
		rdata[0].next = &rdata[1];
		cnt++;
	}

	rdata[cnt].buffer = InvalidBuffer;
	rdata[cnt].data = (char *) &data;
	rdata[cnt].len = sizeof(ginxlogInsert);
	rdata[cnt].next = &rdata[cnt + 1];
	cnt++;

	rdata[cnt].buffer = InvalidBuffer;
	rdata[cnt].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
	rdata[cnt].len = sizeofitem;
	rdata[cnt].next = NULL;

	if (GinPageIsLeaf(page))
	{
		if (GinPageRightMost(page) && off > GinPageGetOpaque(page)->maxoff)
		{
			/* usually, create index... */
			uint32		savedPos = btree->curitem;

			while (btree->curitem < btree->nitem)
			{
				GinDataPageAddItemPointer(page, btree->items + btree->curitem, off);
				off++;
				btree->curitem++;
			}
			data.nitem = btree->curitem - savedPos;
			rdata[cnt].len = sizeofitem * data.nitem;
		}
		else
		{
			GinDataPageAddItemPointer(page, btree->items + btree->curitem, off);
			btree->curitem++;
		}
	}
	else
		GinDataPageAddPostingItem(page, &(btree->pitem), off);
}