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

📄 bufpage.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
					ereport(ERROR,							(errcode(ERRCODE_DATA_CORRUPTED),							 errmsg("corrupted item pointer: %u",									itemidptr->itemoff)));				itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));				totallen += itemidptr->alignedlen;				itemidptr++;			}		}		if (totallen > (Size) (pd_special - pd_lower))			ereport(ERROR,					(errcode(ERRCODE_DATA_CORRUPTED),			   errmsg("corrupted item lengths: total %u, available space %u",					  (unsigned int) totallen, pd_special - pd_lower)));		/* sort itemIdSortData array into decreasing itemoff order */		qsort((char *) itemidbase, nstorage, sizeof(itemIdSortData),			  itemoffcompare);		/* compactify page */		upper = pd_special;		for (i = 0, itemidptr = itemidbase; i < nstorage; i++, itemidptr++)		{			lp = PageGetItemId(page, itemidptr->offsetindex + 1);			upper -= itemidptr->alignedlen;			memmove((char *) page + upper,					(char *) page + itemidptr->itemoff,					itemidptr->alignedlen);			lp->lp_off = upper;		}		((PageHeader) page)->pd_upper = upper;		pfree(itemidbase);	}	/* Set hint bit for PageAddItem */	if (nunused > 0)		PageSetHasFreeLinePointers(page);	else		PageClearHasFreeLinePointers(page);}/* * PageGetFreeSpace *		Returns the size of the free (allocatable) space on a page, *		reduced by the space needed for a new line pointer. * * Note: this should usually only be used on index pages.  Use * PageGetHeapFreeSpace on heap pages. */SizePageGetFreeSpace(Page page){	int			space;	/*	 * Use signed arithmetic here so that we behave sensibly if pd_lower >	 * pd_upper.	 */	space = (int) ((PageHeader) page)->pd_upper -		(int) ((PageHeader) page)->pd_lower;	if (space < (int) sizeof(ItemIdData))		return 0;	space -= sizeof(ItemIdData);	return (Size) space;}/* * PageGetExactFreeSpace *		Returns the size of the free (allocatable) space on a page, *		without any consideration for adding/removing line pointers. */SizePageGetExactFreeSpace(Page page){	int			space;	/*	 * Use signed arithmetic here so that we behave sensibly if pd_lower >	 * pd_upper.	 */	space = (int) ((PageHeader) page)->pd_upper -		(int) ((PageHeader) page)->pd_lower;	if (space < 0)		return 0;	return (Size) space;}/* * PageGetHeapFreeSpace *		Returns the size of the free (allocatable) space on a page, *		reduced by the space needed for a new line pointer. * * The difference between this and PageGetFreeSpace is that this will return * zero if there are already MaxHeapTuplesPerPage line pointers in the page * and none are free.  We use this to enforce that no more than * MaxHeapTuplesPerPage line pointers are created on a heap page.  (Although * no more tuples than that could fit anyway, in the presence of redirected * or dead line pointers it'd be possible to have too many line pointers. * To avoid breaking code that assumes MaxHeapTuplesPerPage is a hard limit * on the number of line pointers, we make this extra check.) */SizePageGetHeapFreeSpace(Page page){	Size		space;	space = PageGetFreeSpace(page);	if (space > 0)	{		OffsetNumber offnum,					nline;		/*		 * Are there already MaxHeapTuplesPerPage line pointers in the page?		 */		nline = PageGetMaxOffsetNumber(page);		if (nline >= MaxHeapTuplesPerPage)		{			if (PageHasFreeLinePointers((PageHeader) page))			{				/*				 * Since this is just a hint, we must confirm that there is				 * indeed a free line pointer				 */				for (offnum = FirstOffsetNumber; offnum <= nline; offnum++)				{					ItemId		lp = PageGetItemId(page, offnum);					if (!ItemIdIsUsed(lp))						break;				}				if (offnum > nline)				{					/*					 * The hint is wrong, but we can't clear it here since we					 * don't have the ability to mark the page dirty.					 */					space = 0;				}			}			else			{				/*				 * Although the hint might be wrong, PageAddItem will believe				 * it anyway, so we must believe it too.				 */				space = 0;			}		}	}	return space;}/* * PageIndexTupleDelete * * This routine does the work of removing a tuple from an index page. * * Unlike heap pages, we compact out the line pointer for the removed tuple. */voidPageIndexTupleDelete(Page page, OffsetNumber offnum){	PageHeader	phdr = (PageHeader) page;	char	   *addr;	ItemId		tup;	Size		size;	unsigned	offset;	int			nbytes;	int			offidx;	int			nline;	/*	 * As with PageRepairFragmentation, paranoia seems justified.	 */	if (phdr->pd_lower < SizeOfPageHeaderData ||		phdr->pd_lower > phdr->pd_upper ||		phdr->pd_upper > phdr->pd_special ||		phdr->pd_special > BLCKSZ)		ereport(ERROR,				(errcode(ERRCODE_DATA_CORRUPTED),				 errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",						phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));	nline = PageGetMaxOffsetNumber(page);	if ((int) offnum <= 0 || (int) offnum > nline)		elog(ERROR, "invalid index offnum: %u", offnum);	/* change offset number to offset index */	offidx = offnum - 1;	tup = PageGetItemId(page, offnum);	Assert(ItemIdHasStorage(tup));	size = ItemIdGetLength(tup);	offset = ItemIdGetOffset(tup);	if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||		offset != MAXALIGN(offset) || size != MAXALIGN(size))		ereport(ERROR,				(errcode(ERRCODE_DATA_CORRUPTED),				 errmsg("corrupted item pointer: offset = %u, size = %u",						offset, (unsigned int) size)));	/*	 * First, we want to get rid of the pd_linp entry for the index tuple. We	 * copy all subsequent linp's back one slot in the array. We don't use	 * PageGetItemId, because we are manipulating the _array_, not individual	 * linp's.	 */	nbytes = phdr->pd_lower -		((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr);	if (nbytes > 0)		memmove((char *) &(phdr->pd_linp[offidx]),				(char *) &(phdr->pd_linp[offidx + 1]),				nbytes);	/*	 * Now move everything between the old upper bound (beginning of tuple	 * space) and the beginning of the deleted tuple forward, so that space in	 * the middle of the page is left free.  If we've just deleted the tuple	 * at the beginning of tuple space, then there's no need to do the copy	 * (and bcopy on some architectures SEGV's if asked to move zero bytes).	 */	/* beginning of tuple space */	addr = (char *) page + phdr->pd_upper;	if (offset > phdr->pd_upper)		memmove(addr + size, addr, (int) (offset - phdr->pd_upper));	/* adjust free space boundary pointers */	phdr->pd_upper += size;	phdr->pd_lower -= sizeof(ItemIdData);	/*	 * Finally, we need to adjust the linp entries that remain.	 *	 * Anything that used to be before the deleted tuple's data was moved	 * forward by the size of the deleted tuple.	 */	if (!PageIsEmpty(page))	{		int			i;		nline--;				/* there's one less than when we started */		for (i = 1; i <= nline; i++)		{			ItemId		ii = PageGetItemId(phdr, i);			Assert(ItemIdHasStorage(ii));			if (ItemIdGetOffset(ii) <= offset)				ii->lp_off += size;		}	}}/* * PageIndexMultiDelete * * This routine handles the case of deleting multiple tuples from an * index page at once.	It is considerably faster than a loop around * PageIndexTupleDelete ... however, the caller *must* supply the array * of item numbers to be deleted in item number order! */voidPageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems){	PageHeader	phdr = (PageHeader) page;	Offset		pd_lower = phdr->pd_lower;	Offset		pd_upper = phdr->pd_upper;	Offset		pd_special = phdr->pd_special;	itemIdSort	itemidbase,				itemidptr;	ItemId		lp;	int			nline,				nused;	int			i;	Size		totallen;	Offset		upper;	Size		size;	unsigned	offset;	int			nextitm;	OffsetNumber offnum;	/*	 * If there aren't very many items to delete, then retail	 * PageIndexTupleDelete is the best way.  Delete the items in reverse	 * order so we don't have to think about adjusting item numbers for	 * previous deletions.	 *	 * TODO: tune the magic number here	 */	if (nitems <= 2)	{		while (--nitems >= 0)			PageIndexTupleDelete(page, itemnos[nitems]);		return;	}	/*	 * As with PageRepairFragmentation, paranoia seems justified.	 */	if (pd_lower < SizeOfPageHeaderData ||		pd_lower > pd_upper ||		pd_upper > pd_special ||		pd_special > BLCKSZ ||		pd_special != MAXALIGN(pd_special))		ereport(ERROR,				(errcode(ERRCODE_DATA_CORRUPTED),				 errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",						pd_lower, pd_upper, pd_special)));	/*	 * Scan the item pointer array and build a list of just the ones we are	 * going to keep.  Notice we do not modify the page yet, since we are	 * still validity-checking.	 */	nline = PageGetMaxOffsetNumber(page);	itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline);	itemidptr = itemidbase;	totallen = 0;	nused = 0;	nextitm = 0;	for (offnum = 1; offnum <= nline; offnum++)	{		lp = PageGetItemId(page, offnum);		Assert(ItemIdHasStorage(lp));		size = ItemIdGetLength(lp);		offset = ItemIdGetOffset(lp);		if (offset < pd_upper ||			(offset + size) > pd_special ||			offset != MAXALIGN(offset))			ereport(ERROR,					(errcode(ERRCODE_DATA_CORRUPTED),					 errmsg("corrupted item pointer: offset = %u, size = %u",							offset, (unsigned int) size)));		if (nextitm < nitems && offnum == itemnos[nextitm])		{			/* skip item to be deleted */			nextitm++;		}		else		{			itemidptr->offsetindex = nused;		/* where it will go */			itemidptr->itemoff = offset;			itemidptr->olditemid = *lp;			itemidptr->alignedlen = MAXALIGN(size);			totallen += itemidptr->alignedlen;			itemidptr++;			nused++;		}	}	/* this will catch invalid or out-of-order itemnos[] */	if (nextitm != nitems)		elog(ERROR, "incorrect index offsets supplied");	if (totallen > (Size) (pd_special - pd_lower))		ereport(ERROR,				(errcode(ERRCODE_DATA_CORRUPTED),			   errmsg("corrupted item lengths: total %u, available space %u",					  (unsigned int) totallen, pd_special - pd_lower)));	/* sort itemIdSortData array into decreasing itemoff order */	qsort((char *) itemidbase, nused, sizeof(itemIdSortData),		  itemoffcompare);	/* compactify page and install new itemids */	upper = pd_special;	for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++)	{		lp = PageGetItemId(page, itemidptr->offsetindex + 1);		upper -= itemidptr->alignedlen;		memmove((char *) page + upper,				(char *) page + itemidptr->itemoff,				itemidptr->alignedlen);		*lp = itemidptr->olditemid;		lp->lp_off = upper;	}	phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);	phdr->pd_upper = upper;	pfree(itemidbase);}

⌨️ 快捷键说明

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