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

📄 hashovfl.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
	_hash_checkpage((Page) metap, LH_META_PAGE);	ovflpage = BufferGetPage(ovflbuf);	_hash_checkpage(ovflpage, LH_OVERFLOW_PAGE);	ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);	addr = ovflopaque->hasho_oaddr;	nextblkno = ovflopaque->hasho_nextblkno;	prevblkno = ovflopaque->hasho_prevblkno;	bucket = ovflopaque->hasho_bucket;	MemSet(ovflpage, 0, BufferGetPageSize(ovflbuf));	_hash_wrtbuf(rel, ovflbuf);	/*	 * fix up the bucket chain.  this is a doubly-linked list, so we must	 * fix up the bucket chain members behind and ahead of the overflow	 * page being deleted.	 *	 * XXX this should look like: - lock prev/next - modify/write prev/next	 * (how to do write ordering with a doubly-linked list?) - unlock	 * prev/next	 */	if (BlockNumberIsValid(prevblkno))	{		Buffer		prevbuf = _hash_getbuf(rel, prevblkno, HASH_WRITE);		Page		prevpage = BufferGetPage(prevbuf);		HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);		_hash_checkpage(prevpage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);		Assert(prevopaque->hasho_bucket == bucket);		prevopaque->hasho_nextblkno = nextblkno;		_hash_wrtbuf(rel, prevbuf);	}	if (BlockNumberIsValid(nextblkno))	{		Buffer		nextbuf = _hash_getbuf(rel, nextblkno, HASH_WRITE);		Page		nextpage = BufferGetPage(nextbuf);		HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);		_hash_checkpage(nextpage, LH_OVERFLOW_PAGE);		Assert(nextopaque->hasho_bucket == bucket);		nextopaque->hasho_prevblkno = prevblkno;		_hash_wrtbuf(rel, nextbuf);	}	/*	 * Fix up the overflow page bitmap that tracks this particular	 * overflow page. The bitmap can be found in the MetaPageData array	 * element hashm_mapp[bitmappage].	 */	splitnum = (addr >> SPLITSHIFT);	ovflpgno = (splitnum ? metap->SPARES[splitnum - 1] : 0) + (addr & SPLITMASK) - 1;	if (ovflpgno < metap->LAST_FREED)		metap->LAST_FREED = ovflpgno;	bitmappage = (ovflpgno >> (metap->hashm_bshift + BYTE_TO_BIT));	bitmapbit = ovflpgno & (BMPGSZ_BIT(metap) - 1);	blkno = metap->hashm_mapp[bitmappage];	mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE);	mappage = BufferGetPage(mapbuf);	_hash_checkpage(mappage, LH_BITMAP_PAGE);	freep = HashPageGetBitmap(mappage);	CLRBIT(freep, bitmapbit);	_hash_wrtbuf(rel, mapbuf);	_hash_relbuf(rel, metabuf, HASH_WRITE);	/*	 * now instantiate the page that replaced this one, if it exists, and	 * return that buffer with a write lock.	 */	if (BlockNumberIsValid(nextblkno))		return _hash_getbuf(rel, nextblkno, HASH_WRITE);	else		return InvalidBuffer;}/* *	_hash_initbitmap() * *	 Initialize a new bitmap page.	The metapage has a write-lock upon *	 entering the function. * * 'pnum' is the OverflowPageAddress of the new bitmap page. * 'nbits' is how many bits to clear (i.e., make available) in the new * bitmap page.  the remainder of the bits (as well as the first bit, * representing the bitmap page itself) will be set. * 'ndx' is the 0-based offset of the new bitmap page within the * metapage's array of bitmap page OverflowPageAddresses. */#define INT_MASK		((1 << INT_TO_BIT) -1)int32_hash_initbitmap(Relation rel,				 HashMetaPage metap,				 int32 pnum,				 int32 nbits,				 int32 ndx){	Buffer		buf;	BlockNumber blkno;	Page		pg;	HashPageOpaque op;	uint32	   *freep;	int			clearbytes,				clearints;	blkno = OADDR_TO_BLKNO(pnum);	buf = _hash_getbuf(rel, blkno, HASH_WRITE);	pg = BufferGetPage(buf);	_hash_pageinit(pg, BufferGetPageSize(buf));	op = (HashPageOpaque) PageGetSpecialPointer(pg);	op->hasho_oaddr = InvalidOvflAddress;	op->hasho_prevblkno = InvalidBlockNumber;	op->hasho_nextblkno = InvalidBlockNumber;	op->hasho_flag = LH_BITMAP_PAGE;	op->hasho_bucket = -1;	freep = HashPageGetBitmap(pg);	/* set all of the bits above 'nbits' to 1 */	clearints = ((nbits - 1) >> INT_TO_BIT) + 1;	clearbytes = clearints << INT_TO_BYTE;	MemSet((char *) freep, 0, clearbytes);	MemSet(((char *) freep) + clearbytes, 0xFF,		   BMPGSZ_BYTE(metap) - clearbytes);	freep[clearints - 1] = ALL_SET << (nbits & INT_MASK);	/* bit 0 represents the new bitmap page */	SETBIT(freep, 0);	/* metapage already has a write lock */	metap->hashm_nmaps++;	metap->hashm_mapp[ndx] = blkno;	/* write out the new bitmap page (releasing its locks) */	_hash_wrtbuf(rel, buf);	return 0;}/* *	_hash_squeezebucket(rel, bucket) * *	Try to squeeze the tuples onto pages occuring earlier in the *	bucket chain in an attempt to free overflow pages. When we start *	the "squeezing", the page from which we start taking tuples (the *	"read" page) is the last bucket in the bucket chain and the page *	onto which we start squeezing tuples (the "write" page) is the *	first page in the bucket chain.  The read page works backward and *	the write page works forward; the procedure terminates when the *	read page and write page are the same page. */void_hash_squeezebucket(Relation rel,					HashMetaPage metap,					Bucket bucket){	Buffer		wbuf;	Buffer		rbuf = 0;	BlockNumber wblkno;	BlockNumber rblkno;	Page		wpage;	Page		rpage;	HashPageOpaque wopaque;	HashPageOpaque ropaque;	OffsetNumber woffnum;	OffsetNumber roffnum;	HashItem	hitem;	int			itemsz;/*	  elog(DEBUG, "_hash_squeezebucket: squeezing bucket %d", bucket); */	/*	 * start squeezing into the base bucket page.	 */	wblkno = BUCKET_TO_BLKNO(bucket);	wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE);	wpage = BufferGetPage(wbuf);	_hash_checkpage(wpage, LH_BUCKET_PAGE);	wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);	/*	 * if there aren't any overflow pages, there's nothing to squeeze.	 */	if (!BlockNumberIsValid(wopaque->hasho_nextblkno))	{		_hash_relbuf(rel, wbuf, HASH_WRITE);		return;	}	/*	 * find the last page in the bucket chain by starting at the base	 * bucket page and working forward.	 *	 * XXX if chains tend to be long, we should probably move forward using	 * HASH_READ and then _hash_chgbufaccess to HASH_WRITE when we reach	 * the end.  if they are short we probably don't care very much.  if	 * the hash function is working at all, they had better be short..	 */	ropaque = wopaque;	do	{		rblkno = ropaque->hasho_nextblkno;		if (ropaque != wopaque)			_hash_relbuf(rel, rbuf, HASH_WRITE);		rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE);		rpage = BufferGetPage(rbuf);		_hash_checkpage(rpage, LH_OVERFLOW_PAGE);		Assert(!PageIsEmpty(rpage));		ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage);		Assert(ropaque->hasho_bucket == bucket);	} while (BlockNumberIsValid(ropaque->hasho_nextblkno));	/*	 * squeeze the tuples.	 */	roffnum = FirstOffsetNumber;	for (;;)	{		hitem = (HashItem) PageGetItem(rpage, PageGetItemId(rpage, roffnum));		itemsz = IndexTupleDSize(hitem->hash_itup)			+ (sizeof(HashItemData) - sizeof(IndexTupleData));		itemsz = MAXALIGN(itemsz);		/*		 * walk up the bucket chain, looking for a page big enough for		 * this item.		 */		while (PageGetFreeSpace(wpage) < itemsz)		{			wblkno = wopaque->hasho_nextblkno;			_hash_wrtbuf(rel, wbuf);			if (!BlockNumberIsValid(wblkno) || (rblkno == wblkno))			{				_hash_wrtbuf(rel, rbuf);				/* wbuf is already released */				return;			}			wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE);			wpage = BufferGetPage(wbuf);			_hash_checkpage(wpage, LH_OVERFLOW_PAGE);			Assert(!PageIsEmpty(wpage));			wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);			Assert(wopaque->hasho_bucket == bucket);		}		/*		 * if we're here, we have found room so insert on the "write"		 * page.		 */		woffnum = OffsetNumberNext(PageGetMaxOffsetNumber(wpage));		PageAddItem(wpage, (Item) hitem, itemsz, woffnum, LP_USED);		/*		 * delete the tuple from the "read" page. PageIndexTupleDelete		 * repacks the ItemId array, so 'roffnum' will be "advanced" to		 * the "next" ItemId.		 */		PageIndexTupleDelete(rpage, roffnum);		_hash_wrtnorelbuf(rel, rbuf);		/*		 * if the "read" page is now empty because of the deletion, free		 * it.		 */		if (PageIsEmpty(rpage) && (ropaque->hasho_flag & LH_OVERFLOW_PAGE))		{			rblkno = ropaque->hasho_prevblkno;			Assert(BlockNumberIsValid(rblkno));			/*			 * free this overflow page.  the extra _hash_relbuf is because			 * _hash_freeovflpage gratuitously returns the next page (we			 * want the previous page and will get it ourselves later).			 */			rbuf = _hash_freeovflpage(rel, rbuf);			if (BufferIsValid(rbuf))				_hash_relbuf(rel, rbuf, HASH_WRITE);			if (rblkno == wblkno)			{				/* rbuf is already released */				_hash_wrtbuf(rel, wbuf);				return;			}			rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE);			rpage = BufferGetPage(rbuf);			_hash_checkpage(rpage, LH_OVERFLOW_PAGE);			Assert(!PageIsEmpty(rpage));			ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage);			Assert(ropaque->hasho_bucket == bucket);			roffnum = FirstOffsetNumber;		}	}}

⌨️ 快捷键说明

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