Exemplo n.º 1
0
/*
 * add ItemPointer to a leaf page.
 */
void
GinDataPageAddItemPointer(Page page, ItemPointer data, OffsetNumber offset)
{
	OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff;
	char	   *ptr;

	Assert(ItemPointerIsValid(data));
	Assert(GinPageIsLeaf(page));

	if (offset == InvalidOffsetNumber)
	{
		ptr = (char *) GinDataPageGetItemPointer(page, maxoff + 1);
	}
	else
	{
		ptr = (char *) GinDataPageGetItemPointer(page, offset);
		if (maxoff + 1 - offset != 0)
			memmove(ptr + sizeof(ItemPointerData),
					ptr,
					(maxoff - offset + 1) * sizeof(ItemPointerData));
	}
	memcpy(ptr, data, sizeof(ItemPointerData));

	GinPageGetOpaque(page)->maxoff++;
}
Exemplo n.º 2
0
/*
 * Searches correct position for value on leaf page.
 * Page should be correctly chosen.
 * Returns true if value found on page.
 */
static bool
dataLocateLeafItem(GinBtree btree, GinBtreeStack *stack)
{
	Page		page = BufferGetPage(stack->buffer);
	OffsetNumber low,
				high;
	int			result;

	Assert(GinPageIsLeaf(page));
	Assert(GinPageIsData(page));

	if (btree->fullScan)
	{
		stack->off = FirstOffsetNumber;
		return TRUE;
	}

	low = FirstOffsetNumber;
	high = GinPageGetOpaque(page)->maxoff;

	if (high < low)
	{
		stack->off = FirstOffsetNumber;
		return false;
	}

	high++;

	while (high > low)
	{
		OffsetNumber mid = low + ((high - low) / 2);

		result = ginCompareItemPointers(&btree->itemptr,
										GinDataPageGetItemPointer(page, mid));

		if (result == 0)
		{
			stack->off = mid;
			return true;
		}
		else if (result > 0)
			low = mid + 1;
		else
			high = mid;
	}

	stack->off = high;
	return false;
}
Exemplo n.º 3
0
/*
 * split page and fills WAL record. original buffer(lbuf) leaves untouched,
 * returns shadow page of lbuf filled new data. In leaf page and build mode puts all
 * ItemPointers to pages. Also, in build mode splits data by way to full fulled
 * left page
 */
static Page
dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off,
			  void *insertdata, BlockNumber updateblkno, XLogRecData **prdata)
{
	char	   *ptr;
	OffsetNumber separator;
	ItemPointer bound;
	Page		lpage = PageGetTempPageCopy(BufferGetPage(lbuf));
	bool		isleaf = GinPageIsLeaf(lpage);
	ItemPointerData oldbound = *GinDataPageGetRightBound(lpage);
	int			sizeofitem = GinSizeOfDataPageItem(lpage);
	OffsetNumber maxoff = GinPageGetOpaque(lpage)->maxoff;
	Page		rpage = BufferGetPage(rbuf);
	Size		pageSize = PageGetPageSize(lpage);
	Size		freeSpace;

	/* these must be static so they can be returned to caller */
	static ginxlogSplitData data;
	static XLogRecData rdata[2];
	static char vector[2 * BLCKSZ];

	GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
	freeSpace = GinDataPageGetFreeSpace(rpage);

	*prdata = rdata;

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

		PostingItemSetBlockNumber(pitem, updateblkno);
	}

	if (isleaf)
	{
		memcpy(vector,
			   GinDataPageGetItemPointer(lpage, FirstOffsetNumber),
			   maxoff * sizeof(ItemPointerData));
	}
	else
	{
		memcpy(vector,
			   GinDataPageGetPostingItem(lpage, FirstOffsetNumber),
			   maxoff * sizeof(PostingItem));
	}

	if (isleaf && GinPageRightMost(lpage) && off > GinPageGetOpaque(lpage)->maxoff)
	{
		/* append new items to the end */
		GinBtreeDataLeafInsertData *items = insertdata;

		while (items->curitem < items->nitem &&
			   maxoff * sizeof(ItemPointerData) < 2 * (freeSpace - sizeof(ItemPointerData)))
		{
			memcpy(vector + maxoff * sizeof(ItemPointerData),
				   items->items + items->curitem,
				   sizeof(ItemPointerData));
			maxoff++;
			items->curitem++;
		}
	}
	else
	{
		ptr = vector + (off - 1) * sizeofitem;
		if (maxoff + 1 - off != 0)
			memmove(ptr + sizeofitem, ptr, (maxoff - off + 1) * sizeofitem);
		if (isleaf)
		{
			GinBtreeDataLeafInsertData *items = insertdata;

			memcpy(ptr, items->items + items->curitem, sizeofitem);
			items->curitem++;
		}
		else
		{
			PostingItem *pitem = insertdata;

			memcpy(ptr, pitem, sizeofitem);
		}

		maxoff++;
	}

	/*
	 * we assume that during index creation the table scanned from beginning
	 * to end, so ItemPointers are in monotonically increasing order.
	 */
	if (btree->isBuild && GinPageRightMost(lpage))
		separator = freeSpace / sizeofitem;
	else
		separator = maxoff / 2;

	GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
	GinInitPage(lpage, GinPageGetOpaque(rpage)->flags, pageSize);

	if (isleaf)
		memcpy(GinDataPageGetItemPointer(lpage, FirstOffsetNumber),
			   vector, separator * sizeof(ItemPointerData));
	else
		memcpy(GinDataPageGetPostingItem(lpage, FirstOffsetNumber),
			   vector, separator * sizeof(PostingItem));

	GinPageGetOpaque(lpage)->maxoff = separator;
	if (isleaf)
		memcpy(GinDataPageGetItemPointer(rpage, FirstOffsetNumber),
			   vector + separator * sizeof(ItemPointerData),
			   (maxoff - separator) * sizeof(ItemPointerData));
	else
		memcpy(GinDataPageGetPostingItem(rpage, FirstOffsetNumber),
			   vector + separator * sizeof(PostingItem),
			   (maxoff - separator) * sizeof(PostingItem));

	GinPageGetOpaque(rpage)->maxoff = maxoff - separator;

	/* set up right bound for left page */
	bound = GinDataPageGetRightBound(lpage);
	if (GinPageIsLeaf(lpage))
		*bound = *GinDataPageGetItemPointer(lpage,
											GinPageGetOpaque(lpage)->maxoff);
	else
		*bound = GinDataPageGetPostingItem(lpage,
									   GinPageGetOpaque(lpage)->maxoff)->key;

	/* set up right bound for right page */
	bound = GinDataPageGetRightBound(rpage);
	*bound = oldbound;

	data.separator = separator;
	data.nitem = maxoff;
	data.rightbound = oldbound;

	rdata[0].buffer = InvalidBuffer;
	rdata[0].data = (char *) &data;
	rdata[0].len = sizeof(ginxlogSplitData);
	rdata[0].next = &rdata[1];

	rdata[1].buffer = InvalidBuffer;
	rdata[1].data = vector;
	rdata[1].len = maxoff * sizeofitem;
	rdata[1].next = NULL;

	return lpage;
}
Exemplo n.º 4
0
/*
 * split page and fills WAL record. original buffer(lbuf) leaves untouched,
 * returns shadow page of lbuf filled new data. In leaf page and build mode puts all
 * ItemPointers to pages. Also, in build mode splits data by way to full fulled
 * left page
 */
static Page
dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRecData **prdata)
{
	char	   *ptr;
	OffsetNumber separator;
	ItemPointer bound;
	Page		lpage = PageGetTempPageCopy(BufferGetPage(lbuf));
	bool		isleaf = GinPageIsLeaf(lpage);
	ItemPointerData oldbound = *GinDataPageGetRightBound(lpage);
	int			sizeofitem = GinSizeOfDataPageItem(lpage);
	OffsetNumber maxoff = GinPageGetOpaque(lpage)->maxoff;
	Page		rpage = BufferGetPage(rbuf);
	Size		pageSize = PageGetPageSize(lpage);
	Size		freeSpace;
	uint32		nCopied = 1;

	/* these must be static so they can be returned to caller */
	static ginxlogSplit data;
	static XLogRecData rdata[4];
	static char vector[2 * BLCKSZ];

	GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
	freeSpace = GinDataPageGetFreeSpace(rpage);

	*prdata = rdata;
	data.leftChildBlkno = (GinPageIsLeaf(lpage)) ?
		InvalidOffsetNumber : PostingItemGetBlockNumber(&(btree->pitem));
	data.updateBlkno = dataPrepareData(btree, lpage, off);

	if (isleaf)
	{
		memcpy(vector,
			   GinDataPageGetItemPointer(lpage, FirstOffsetNumber),
			   maxoff * sizeof(ItemPointerData));
	}
	else
	{
		memcpy(vector,
			   GinDataPageGetPostingItem(lpage, FirstOffsetNumber),
			   maxoff * sizeof(PostingItem));
	}

	if (isleaf && GinPageRightMost(lpage) && off > GinPageGetOpaque(lpage)->maxoff)
	{
		nCopied = 0;
		while (btree->curitem < btree->nitem &&
			   maxoff * sizeof(ItemPointerData) < 2 * (freeSpace - sizeof(ItemPointerData)))
		{
			memcpy(vector + maxoff * sizeof(ItemPointerData),
				   btree->items + btree->curitem,
				   sizeof(ItemPointerData));
			maxoff++;
			nCopied++;
			btree->curitem++;
		}
	}
	else
	{
		ptr = vector + (off - 1) * sizeofitem;
		if (maxoff + 1 - off != 0)
			memmove(ptr + sizeofitem, ptr, (maxoff - off + 1) * sizeofitem);
		if (isleaf)
		{
			memcpy(ptr, btree->items + btree->curitem, sizeofitem);
			btree->curitem++;
		}
		else
			memcpy(ptr, &(btree->pitem), sizeofitem);

		maxoff++;
	}

	/*
	 * we suppose that during index creation table scaned from begin to end,
	 * so ItemPointers are monotonically increased..
	 */
	if (btree->isBuild && GinPageRightMost(lpage))
		separator = freeSpace / sizeofitem;
	else
		separator = maxoff / 2;

	GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
	GinInitPage(lpage, GinPageGetOpaque(rpage)->flags, pageSize);

	if (isleaf)
		memcpy(GinDataPageGetItemPointer(lpage, FirstOffsetNumber),
			   vector, separator * sizeof(ItemPointerData));
	else
		memcpy(GinDataPageGetPostingItem(lpage, FirstOffsetNumber),
			   vector, separator * sizeof(PostingItem));

	GinPageGetOpaque(lpage)->maxoff = separator;
	if (isleaf)
		memcpy(GinDataPageGetItemPointer(rpage, FirstOffsetNumber),
			   vector + separator * sizeof(ItemPointerData),
			   (maxoff - separator) * sizeof(ItemPointerData));
	else
		memcpy(GinDataPageGetPostingItem(rpage, FirstOffsetNumber),
			   vector + separator * sizeof(PostingItem),
			   (maxoff - separator) * sizeof(PostingItem));

	GinPageGetOpaque(rpage)->maxoff = maxoff - separator;

	PostingItemSetBlockNumber(&(btree->pitem), BufferGetBlockNumber(lbuf));
	if (GinPageIsLeaf(lpage))
		btree->pitem.key = *GinDataPageGetItemPointer(lpage,
											GinPageGetOpaque(lpage)->maxoff);
	else
		btree->pitem.key = GinDataPageGetPostingItem(lpage,
									  GinPageGetOpaque(lpage)->maxoff)->key;
	btree->rightblkno = BufferGetBlockNumber(rbuf);

	/* set up right bound for left page */
	bound = GinDataPageGetRightBound(lpage);
	*bound = btree->pitem.key;

	/* set up right bound for right page */
	bound = GinDataPageGetRightBound(rpage);
	*bound = oldbound;

	data.node = btree->index->rd_node;
	data.rootBlkno = InvalidBlockNumber;
	data.lblkno = BufferGetBlockNumber(lbuf);
	data.rblkno = BufferGetBlockNumber(rbuf);
	data.separator = separator;
	data.nitem = maxoff;
	data.isData = TRUE;
	data.isLeaf = GinPageIsLeaf(lpage) ? TRUE : FALSE;
	data.isRootSplit = FALSE;
	data.rightbound = oldbound;

	rdata[0].buffer = InvalidBuffer;
	rdata[0].data = (char *) &data;
	rdata[0].len = sizeof(ginxlogSplit);
	rdata[0].next = &rdata[1];

	rdata[1].buffer = InvalidBuffer;
	rdata[1].data = vector;
	rdata[1].len = MAXALIGN(maxoff * sizeofitem);
	rdata[1].next = NULL;

	return lpage;
}