Beispiel #1
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;
}
Beispiel #2
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);
}