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

📄 rtree.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
	rightbuf = ReadBuffer(r, P_NEW);	RTInitBuffer(rightbuf, opaque->flags);	rbknum = BufferGetBlockNumber(rightbuf);	right = (Page) BufferGetPage(rightbuf);	picksplit(r, p, &v, itup, rtstate);	leftoff = rightoff = FirstOffsetNumber;	maxoff = PageGetMaxOffsetNumber(p);	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))	{		itemid = PageGetItemId(p, i);		item = (IndexTuple) PageGetItem(p, itemid);		if (i == *(v.spl_left))		{			PageAddItem(left, (Item) item, IndexTupleSize(item),						leftoff, LP_USED);			leftoff = OffsetNumberNext(leftoff);			v.spl_left++;		/* advance in left split vector */		}		else		{			PageAddItem(right, (Item) item, IndexTupleSize(item),						rightoff, LP_USED);			rightoff = OffsetNumberNext(rightoff);			v.spl_right++;		/* advance in right split vector */		}	}	/* build an InsertIndexResult for this insertion */	res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));	/* now insert the new index tuple */	if (*(v.spl_left) != FirstOffsetNumber)	{		PageAddItem(left, (Item) itup, IndexTupleSize(itup),					leftoff, LP_USED);		leftoff = OffsetNumberNext(leftoff);		ItemPointerSet(&(res->pointerData), lbknum, leftoff);	}	else	{		PageAddItem(right, (Item) itup, IndexTupleSize(itup),					rightoff, LP_USED);		rightoff = OffsetNumberNext(rightoff);		ItemPointerSet(&(res->pointerData), rbknum, rightoff);	}	if ((bufblock = BufferGetBlockNumber(buffer)) != P_ROOT)		PageRestoreTempPage(left, p);	WriteBuffer(leftbuf);	WriteBuffer(rightbuf);	/*	 * Okay, the page is split.  We have three things left to do:	 *	 * 1)  Adjust any active scans on this index to cope with changes we	 * introduced in its structure by splitting this page.	 *	 * 2)  "Tighten" the bounding box of the pointer to the left page in the	 * parent node in the tree, if any.  Since we moved a bunch of stuff	 * off the left page, we expect it to get smaller.	This happens in	 * the internal insertion routine.	 *	 * 3)  Insert a pointer to the right page in the parent.  This may cause	 * the parent to split.  If it does, we need to repeat steps one and	 * two for each split node in the tree.	 */	/* adjust active scans */	rtadjscans(r, RTOP_SPLIT, bufblock, FirstOffsetNumber);	tupDesc = r->rd_att;	ltup = (IndexTuple) index_formtuple(tupDesc,									  (Datum *) &(v.spl_ldatum), isnull);	rtup = (IndexTuple) index_formtuple(tupDesc,									  (Datum *) &(v.spl_rdatum), isnull);	pfree(isnull);	/* set pointers to new child pages in the internal index tuples */	ItemPointerSet(&(ltup->t_tid), lbknum, 1);	ItemPointerSet(&(rtup->t_tid), rbknum, 1);	rtintinsert(r, stack, ltup, rtup, rtstate);	pfree(ltup);	pfree(rtup);	return res;}static voidrtintinsert(Relation r,			RTSTACK *stk,			IndexTuple ltup,			IndexTuple rtup,			RTSTATE *rtstate){	IndexTuple	old;	Buffer		b;	Page		p;	char	   *ldatum,			   *rdatum,			   *newdatum;	InsertIndexResult res;	if (stk == (RTSTACK *) NULL)	{		rtnewroot(r, ltup, rtup);		return;	}	b = ReadBuffer(r, stk->rts_blk);	p = BufferGetPage(b);	old = (IndexTuple) PageGetItem(p, PageGetItemId(p, stk->rts_child));	/*	 * This is a hack.	Right now, we force rtree keys to be constant	 * size. To fix this, need delete the old key and add both left and	 * right for the two new pages.  The insertion of left may force a	 * split if the new left key is bigger than the old key.	 */	if (IndexTupleSize(old) != IndexTupleSize(ltup))		elog(ERROR, "Variable-length rtree keys are not supported.");	/* install pointer to left child */	memmove(old, ltup, IndexTupleSize(ltup));	if (nospace(p, rtup))	{		newdatum = (((char *) ltup) + sizeof(IndexTupleData));		rttighten(r, stk->rts_parent, newdatum,			   (IndexTupleSize(ltup) - sizeof(IndexTupleData)), rtstate);		res = dosplit(r, b, stk->rts_parent, rtup, rtstate);		WriteBuffer(b);			/* don't forget to release buffer!  -								 * 01/31/94 */		pfree(res);	}	else	{		PageAddItem(p, (Item) rtup, IndexTupleSize(rtup),					PageGetMaxOffsetNumber(p), LP_USED);		WriteBuffer(b);		ldatum = (((char *) ltup) + sizeof(IndexTupleData));		rdatum = (((char *) rtup) + sizeof(IndexTupleData));		newdatum = (char *) (*fmgr_faddr(&rtstate->unionFn)) (ldatum, rdatum);		rttighten(r, stk->rts_parent, newdatum,			   (IndexTupleSize(rtup) - sizeof(IndexTupleData)), rtstate);		pfree(newdatum);	}}static voidrtnewroot(Relation r, IndexTuple lt, IndexTuple rt){	Buffer		b;	Page		p;	b = ReadBuffer(r, P_ROOT);	RTInitBuffer(b, 0);	p = BufferGetPage(b);	PageAddItem(p, (Item) lt, IndexTupleSize(lt),				FirstOffsetNumber, LP_USED);	PageAddItem(p, (Item) rt, IndexTupleSize(rt),				OffsetNumberNext(FirstOffsetNumber), LP_USED);	WriteBuffer(b);}static voidpicksplit(Relation r,		  Page page,		  SPLITVEC *v,		  IndexTuple itup,		  RTSTATE *rtstate){	OffsetNumber maxoff;	OffsetNumber i,				j;	IndexTuple	item_1,				item_2;	char	   *datum_alpha,			   *datum_beta;	char	   *datum_l,			   *datum_r;	char	   *union_d,			   *union_dl,			   *union_dr;	char	   *inter_d;	bool		firsttime;	float		size_alpha,				size_beta,				size_union,				size_inter;	float		size_waste,				waste;	float		size_l,				size_r;	int			nbytes;	OffsetNumber seed_1 = 0,				seed_2 = 0;	OffsetNumber *left,			   *right;	maxoff = PageGetMaxOffsetNumber(page);	nbytes = (maxoff + 2) * sizeof(OffsetNumber);	v->spl_left = (OffsetNumber *) palloc(nbytes);	v->spl_right = (OffsetNumber *) palloc(nbytes);	firsttime = true;	waste = 0.0;	for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))	{		item_1 = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));		datum_alpha = ((char *) item_1) + sizeof(IndexTupleData);		for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))		{			item_2 = (IndexTuple) PageGetItem(page, PageGetItemId(page, j));			datum_beta = ((char *) item_2) + sizeof(IndexTupleData);			/* compute the wasted space by unioning these guys */			union_d = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_alpha, datum_beta);			(*fmgr_faddr(&rtstate->sizeFn)) (union_d, &size_union);			inter_d = (char *) (*fmgr_faddr(&rtstate->interFn)) (datum_alpha, datum_beta);			(*fmgr_faddr(&rtstate->sizeFn)) (inter_d, &size_inter);			size_waste = size_union - size_inter;			pfree(union_d);			if (inter_d != (char *) NULL)				pfree(inter_d);			/*			 * are these a more promising split that what we've already			 * seen?			 */			if (size_waste > waste || firsttime)			{				waste = size_waste;				seed_1 = i;				seed_2 = j;				firsttime = false;			}		}	}	left = v->spl_left;	v->spl_nleft = 0;	right = v->spl_right;	v->spl_nright = 0;	item_1 = (IndexTuple) PageGetItem(page, PageGetItemId(page, seed_1));	datum_alpha = ((char *) item_1) + sizeof(IndexTupleData);	datum_l = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_alpha, datum_alpha);	(*fmgr_faddr(&rtstate->sizeFn)) (datum_l, &size_l);	item_2 = (IndexTuple) PageGetItem(page, PageGetItemId(page, seed_2));	datum_beta = ((char *) item_2) + sizeof(IndexTupleData);	datum_r = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_beta, datum_beta);	(*fmgr_faddr(&rtstate->sizeFn)) (datum_r, &size_r);	/*	 * Now split up the regions between the two seeds.	An important	 * property of this split algorithm is that the split vector v has the	 * indices of items to be split in order in its left and right	 * vectors.  We exploit this property by doing a merge in the code	 * that actually splits the page.	 *	 * For efficiency, we also place the new index tuple in this loop. This	 * is handled at the very end, when we have placed all the existing	 * tuples and i == maxoff + 1.	 */	maxoff = OffsetNumberNext(maxoff);	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))	{		/*		 * If we've already decided where to place this item, just put it		 * on the right list.  Otherwise, we need to figure out which page		 * needs the least enlargement in order to store the item.		 */		if (i == seed_1)		{			*left++ = i;			v->spl_nleft++;			continue;		}		else if (i == seed_2)		{			*right++ = i;			v->spl_nright++;			continue;		}		/* okay, which page needs least enlargement? */		if (i == maxoff)			item_1 = itup;		else			item_1 = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));		datum_alpha = ((char *) item_1) + sizeof(IndexTupleData);		union_dl = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_l, datum_alpha);		union_dr = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_r, datum_alpha);		(*fmgr_faddr(&rtstate->sizeFn)) (union_dl, &size_alpha);		(*fmgr_faddr(&rtstate->sizeFn)) (union_dr, &size_beta);		/* pick which page to add it to */		if (size_alpha - size_l < size_beta - size_r)		{			pfree(datum_l);			pfree(union_dr);			datum_l = union_dl;			size_l = size_alpha;			*left++ = i;			v->spl_nleft++;		}		else		{			pfree(datum_r);			pfree(union_dl);			datum_r = union_dr;			size_r = size_alpha;			*right++ = i;			v->spl_nright++;		}	}	*left = *right = FirstOffsetNumber; /* sentinel value, see dosplit() */	v->spl_ldatum = datum_l;	v->spl_rdatum = datum_r;}static voidRTInitBuffer(Buffer b, uint32 f){	RTreePageOpaque opaque;	Page		page;	Size		pageSize;	pageSize = BufferGetPageSize(b);	page = BufferGetPage(b);	MemSet(page, 0, (int) pageSize);	PageInit(page, pageSize, sizeof(RTreePageOpaqueData));	opaque = (RTreePageOpaque) PageGetSpecialPointer(page);	opaque->flags = f;}static OffsetNumberchoose(Relation r, Page p, IndexTuple it, RTSTATE *rtstate){	OffsetNumber maxoff;	OffsetNumber i;	char	   *ud,			   *id;	char	   *datum;	float		usize,				dsize;	OffsetNumber which;	float		which_grow;	id = ((char *) it) + sizeof(IndexTupleData);	maxoff = PageGetMaxOffsetNumber(p);	which_grow = -1.0;	which = -1;	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))	{		datum = (char *) PageGetItem(p, PageGetItemId(p, i));		datum += sizeof(IndexTupleData);		(*fmgr_faddr(&rtstate->sizeFn)) (datum, &dsize);		ud = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum, id);		(*fmgr_faddr(&rtstate->sizeFn)) (ud, &usize);		pfree(ud);		if (which_grow < 0 || usize - dsize < which_grow)		{			which = i;			which_grow = usize - dsize;			if (which_grow == 0)				break;		}	}	return which;}static intnospace(Page p, IndexTuple it){	return PageGetFreeSpace(p) < IndexTupleSize(it);}voidfreestack(RTSTACK *s){	RTSTACK    *p;	while (s != (RTSTACK *) NULL)	{		p = s->rts_parent;		pfree(s);		s = p;	}}char *rtdelete(Relation r, ItemPointer tid){	BlockNumber blkno;	OffsetNumber offnum;	Buffer		buf;	Page		page;	/*	 * Notes in ExecUtils:ExecOpenIndices() Also note that only vacuum	 * deletes index tuples now...	 *	 * RelationSetLockForWrite(r);	 */	blkno = ItemPointerGetBlockNumber(tid);	offnum = ItemPointerGetOffsetNumber(tid);	/* adjust any scans that will be affected by this deletion */	rtadjscans(r, RTOP_DEL, blkno, offnum);	/* delete the index tuple */	buf = ReadBuffer(r, blkno);	page = BufferGetPage(buf);	PageIndexTupleDelete(page, offnum);	WriteBuffer(buf);	return (char *) NULL;}static voidinitRtstate(RTSTATE *rtstate, Relation index){	RegProcedure union_proc,				size_proc,				inter_proc;	union_proc = index_getprocid(index, 1, RT_UNION_PROC);	size_proc = index_getprocid(index, 1, RT_SIZE_PROC);	inter_proc = index_getprocid(index, 1, RT_INTER_PROC);	fmgr_info(union_proc, &rtstate->unionFn);	fmgr_info(size_proc, &rtstate->sizeFn);	fmgr_info(inter_proc, &rtstate->interFn);	return;}#ifdef RTDEBUGvoid_rtdump(Relation r){	Buffer		buf;	Page		page;	OffsetNumber offnum,				maxoff;	BlockNumber blkno;	BlockNumber nblocks;	RTreePageOpaque po;	IndexTuple	itup;	BlockNumber itblkno;	OffsetNumber itoffno;	char	   *datum;	char	   *itkey;	nblocks = RelationGetNumberOfBlocks(r);	for (blkno = 0; blkno < nblocks; blkno++)	{		buf = ReadBuffer(r, blkno);		page = BufferGetPage(buf);		po = (RTreePageOpaque) PageGetSpecialPointer(page);		maxoff = PageGetMaxOffsetNumber(page);		printf("Page %d maxoff %d <%s>\n", blkno, maxoff,			   (po->flags & F_LEAF ? "LEAF" : "INTERNAL"));		if (PageIsEmpty(page))		{			ReleaseBuffer(buf);			continue;		}		for (offnum = FirstOffsetNumber;			 offnum <= maxoff;			 offnum = OffsetNumberNext(offnum))		{			itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));			itblkno = ItemPointerGetBlockNumber(&(itup->t_tid));			itoffno = ItemPointerGetOffsetNumber(&(itup->t_tid));			datum = ((char *) itup);			datum += sizeof(IndexTupleData);			itkey = (char *) box_out((BOX *) datum);			printf("\t[%d] size %d heap <%d,%d> key:%s\n",				   offnum, IndexTupleSize(itup), itblkno, itoffno, itkey);			pfree(itkey);		}		ReleaseBuffer(buf);	}}#endif	 /* defined RTDEBUG */

⌨️ 快捷键说明

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