⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gist.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
			opaque->nsn = PageGetLSN(page);			opaque->rightlink = ourpage->next->block.blkno;			/*			 * fills and write all new pages. They isn't linked into tree yet			 */			ptr = ourpage->next;			while (ptr)			{				page = (Page) BufferGetPage(ptr->buffer);				GistPageGetOpaque(page)->rightlink = (ptr->next) ?					ptr->next->block.blkno : rightrightlink;				/* only for last set oldnsn */				GistPageGetOpaque(page)->nsn = (ptr->next) ?					opaque->nsn : oldnsn;				LockBuffer(ptr->buffer, GIST_UNLOCK);				WriteBuffer(ptr->buffer);				ptr = ptr->next;			}		}		WriteNoReleaseBuffer(state->stack->buffer);	}	else	{		/* enough space */		XLogRecPtr	oldlsn;		gistfillbuffer(state->r, state->stack->page, state->itup, state->ituplen, InvalidOffsetNumber);		oldlsn = PageGetLSN(state->stack->page);		if (!state->r->rd_istemp)		{			OffsetNumber noffs = 0,						offs[MAXALIGN(sizeof(OffsetNumber)) / sizeof(OffsetNumber)];			XLogRecPtr	recptr;			XLogRecData *rdata;			if (!is_leaf)			{				/* only on inner page we should delete previous version */				offs[0] = state->stack->childoffnum;				noffs = 1;			}			rdata = formUpdateRdata(state->r->rd_node, state->stack->blkno,							 offs, noffs, false, state->itup, state->ituplen,									&(state->key));			START_CRIT_SECTION();			recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_ENTRY_UPDATE, rdata);			PageSetLSN(state->stack->page, recptr);			PageSetTLI(state->stack->page, ThisTimeLineID);			END_CRIT_SECTION();		}		else			PageSetLSN(state->stack->page, XLogRecPtrForTemp);		if (state->stack->blkno == GIST_ROOT_BLKNO)			state->needInsertComplete = false;		WriteNoReleaseBuffer(state->stack->buffer);		if (!is_leaf)			/* small optimization: inform scan ablout								 * deleting... */			gistadjscans(state->r, GISTOP_DEL, state->stack->blkno,						 state->stack->childoffnum, PageGetLSN(state->stack->page), oldlsn);		if (state->ituplen > 1)		{						/* previous is_splitted==true */			/*			 * child was splited, so we must form union for insertion in			 * parent			 */			IndexTuple	newtup = gistunion(state->r, state->itup, state->ituplen, giststate);			ItemPointerSetBlockNumber(&(newtup->t_tid), state->stack->blkno);			state->itup[0] = newtup;			state->ituplen = 1;		}		else if (is_leaf)		{			/*			 * itup[0] store key to adjust parent, we set it to valid to			 * correct check by GistTupleIsInvalid macro in gistgetadjusted()			 */			ItemPointerSetBlockNumber(&(state->itup[0]->t_tid), state->stack->blkno);			GistTupleSetValid(state->itup[0]);		}	}	return is_splitted;}/* * returns stack of pages, all pages in stack are pinned, and * leaf is X-locked */static voidgistfindleaf(GISTInsertState *state, GISTSTATE *giststate){	ItemId		iid;	IndexTuple	idxtuple;	GISTPageOpaque opaque;	/*	 * walk down, We don't lock page for a long time, but so we should be	 * ready to recheck path in a bad case... We remember, that page->lsn	 * should never be invalid.	 */	while (true)	{		if (XLogRecPtrIsInvalid(state->stack->lsn))			state->stack->buffer = ReadBuffer(state->r, state->stack->blkno);		LockBuffer(state->stack->buffer, GIST_SHARE);		state->stack->page = (Page) BufferGetPage(state->stack->buffer);		opaque = GistPageGetOpaque(state->stack->page);		state->stack->lsn = PageGetLSN(state->stack->page);		Assert(state->r->rd_istemp || !XLogRecPtrIsInvalid(state->stack->lsn));		if (state->stack->blkno != GIST_ROOT_BLKNO &&			XLByteLT(state->stack->parent->lsn, opaque->nsn))		{			/*			 * caused split non-root page is detected, go up to parent to			 * choose best child			 */			LockBuffer(state->stack->buffer, GIST_UNLOCK);			ReleaseBuffer(state->stack->buffer);			state->stack = state->stack->parent;			continue;		}		if (!GistPageIsLeaf(state->stack->page))		{			/*			 * This is an internal page, so continue to walk down the tree. We			 * find the child node that has the minimum insertion penalty and			 * recursively invoke ourselves to modify that node. Once the			 * recursive call returns, we may need to adjust the parent node			 * for two reasons: the child node split, or the key in this node			 * needs to be adjusted for the newly inserted key below us.			 */			GISTInsertStack *item = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));			state->stack->childoffnum = gistchoose(state->r, state->stack->page, state->itup[0], giststate);			iid = PageGetItemId(state->stack->page, state->stack->childoffnum);			idxtuple = (IndexTuple) PageGetItem(state->stack->page, iid);			item->blkno = ItemPointerGetBlockNumber(&(idxtuple->t_tid));			LockBuffer(state->stack->buffer, GIST_UNLOCK);			item->parent = state->stack;			item->child = NULL;			if (state->stack)				state->stack->child = item;			state->stack = item;		}		else		{			/* be carefull, during unlock/lock page may be changed... */			LockBuffer(state->stack->buffer, GIST_UNLOCK);			LockBuffer(state->stack->buffer, GIST_EXCLUSIVE);			state->stack->page = (Page) BufferGetPage(state->stack->buffer);			opaque = GistPageGetOpaque(state->stack->page);			if (state->stack->blkno == GIST_ROOT_BLKNO)			{				/*				 * the only page can become inner instead of leaf is a root				 * page, so for root we should recheck it				 */				if (!GistPageIsLeaf(state->stack->page))				{					/*					 * very rarely situation: during unlock/lock index with					 * number of pages = 1 was increased					 */					LockBuffer(state->stack->buffer, GIST_UNLOCK);					continue;				}				/*				 * we don't need to check root split, because checking				 * leaf/inner is enough to recognize split for root				 */			}			else if (XLByteLT(state->stack->parent->lsn, opaque->nsn))			{				/*				 * detecting split during unlock/lock, so we should find				 * better child on parent				 */				/* forget buffer */				LockBuffer(state->stack->buffer, GIST_UNLOCK);				ReleaseBuffer(state->stack->buffer);				state->stack = state->stack->parent;				continue;			}			state->stack->lsn = PageGetLSN(state->stack->page);			/* ok we found a leaf page and it X-locked */			break;		}	}	/* now state->stack->(page, buffer and blkno) points to leaf page */}/* * Should have the same interface as XLogReadBuffer */static BuffergistReadAndLockBuffer(Relation r, BlockNumber blkno){	Buffer		buffer = ReadBuffer(r, blkno);	LockBuffer(buffer, GIST_SHARE);	return buffer;}/* * Traverse the tree to find path from root page, * to prevent deadlocks, it should lock only one page simultaneously. * Function uses in recovery and usial mode, so should work with different * read functions (gistReadAndLockBuffer and XLogReadBuffer) * returns from the begining of closest parent; */GISTInsertStack *gistFindPath(Relation r, BlockNumber child, Buffer (*myReadBuffer) (Relation, BlockNumber)){	Page		page;	Buffer		buffer;	OffsetNumber i,				maxoff;	ItemId		iid;	IndexTuple	idxtuple;	GISTInsertStack *top,			   *tail,			   *ptr;	BlockNumber blkno;	top = tail = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));	top->blkno = GIST_ROOT_BLKNO;	while (top && top->blkno != child)	{		buffer = myReadBuffer(r, top->blkno);	/* buffer locked */		page = (Page) BufferGetPage(buffer);		if (GistPageIsLeaf(page))		{			/* we can safety go away, follows only leaf pages */			LockBuffer(buffer, GIST_UNLOCK);			ReleaseBuffer(buffer);			return NULL;		}		top->lsn = PageGetLSN(page);		if (top->parent && XLByteLT(top->parent->lsn, GistPageGetOpaque(page)->nsn) &&			GistPageGetOpaque(page)->rightlink != InvalidBlockNumber /* sanity check */ )		{			/* page splited while we thinking of... */			ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));			ptr->blkno = GistPageGetOpaque(page)->rightlink;			ptr->childoffnum = InvalidOffsetNumber;			ptr->parent = top;			ptr->next = NULL;			tail->next = ptr;			tail = ptr;		}		maxoff = PageGetMaxOffsetNumber(page);		for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))		{			iid = PageGetItemId(page, i);			idxtuple = (IndexTuple) PageGetItem(page, iid);			blkno = ItemPointerGetBlockNumber(&(idxtuple->t_tid));			if (blkno == child)			{				OffsetNumber poff = InvalidOffsetNumber;				/* make childs links */				ptr = top;				while (ptr->parent)				{					/* set child link */					ptr->parent->child = ptr;					/* move childoffnum.. */					if (ptr == top)					{						/* first iteration */						poff = ptr->parent->childoffnum;						ptr->parent->childoffnum = ptr->childoffnum;					}					else					{						OffsetNumber tmp = ptr->parent->childoffnum;						ptr->parent->childoffnum = poff;						poff = tmp;					}					ptr = ptr->parent;				}				top->childoffnum = i;				LockBuffer(buffer, GIST_UNLOCK);				ReleaseBuffer(buffer);				return top;			}			else			{				/* Install next inner page to the end of stack */				ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));				ptr->blkno = blkno;				ptr->childoffnum = i;	/* set offsetnumber of child to child										 * !!! */				ptr->parent = top;				ptr->next = NULL;				tail->next = ptr;				tail = ptr;			}		}		LockBuffer(buffer, GIST_UNLOCK);		ReleaseBuffer(buffer);		top = top->next;	}	return NULL;}/* * Returns X-locked parent of stack page */static voidgistFindCorrectParent(Relation r, GISTInsertStack *child){	GISTInsertStack *parent = child->parent;	LockBuffer(parent->buffer, GIST_EXCLUSIVE);	parent->page = (Page) BufferGetPage(parent->buffer);	/* here we don't need to distinguish between split and page update */	if (parent->childoffnum == InvalidOffsetNumber || !XLByteEQ(parent->lsn, PageGetLSN(parent->page)))	{		/* parent is changed, look child in right links until found */		OffsetNumber i,					maxoff;		ItemId		iid;		IndexTuple	idxtuple;		GISTInsertStack *ptr;		while (true)		{			maxoff = PageGetMaxOffsetNumber(parent->page);			for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))			{				iid = PageGetItemId(parent->page, i);				idxtuple = (IndexTuple) PageGetItem(parent->page, iid);				if (ItemPointerGetBlockNumber(&(idxtuple->t_tid)) == child->blkno)				{					/* yes!!, found */					parent->childoffnum = i;					return;				}			}			parent->blkno = GistPageGetOpaque(parent->page)->rightlink;			LockBuffer(parent->buffer, GIST_UNLOCK);			ReleaseBuffer(parent->buffer);			if (parent->blkno == InvalidBlockNumber)				/*				 * end of chain and still didn't found parent, It's very-very				 * rare situation when root splited				 */				break;			parent->buffer = ReadBuffer(r, parent->blkno);			LockBuffer(parent->buffer, GIST_EXCLUSIVE);			parent->page = (Page) BufferGetPage(parent->buffer);		}		/*		 * awful!!, we need search tree to find parent ... , but before we		 * should release all old parent		 */		ptr = child->parent->parent;	/* child->parent already released										 * above */		while (ptr)		{			ReleaseBuffer(ptr->buffer);			ptr = ptr->parent;		}		/* ok, find new path */		ptr = parent = gistFindPath(r, child->blkno, gistReadAndLockBuffer);		Assert(ptr != NULL);		/* read all buffers as supposed in caller */		while (ptr)		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -