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

📄 gistvacuum.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		pfree(addon);	if (completed)		pfree(completed);	return res;}/* * For usial vacuum just update FSM, for full vacuum * reforms parent tuples if some of childs was deleted or changed, * update invalid tuples (they can exsist from last crash recovery only), * tries to get smaller index */Datumgistvacuumcleanup(PG_FUNCTION_ARGS){	Relation	rel = (Relation) PG_GETARG_POINTER(0);	IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);	IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);	BlockNumber npages,				blkno;	BlockNumber nFreePages,			   *freePages,				maxFreePages;	BlockNumber lastBlock = GIST_ROOT_BLKNO,				lastFilledBlock = GIST_ROOT_BLKNO;	bool		needLock;	/* gistVacuumUpdate may cause hard work */	if (info->vacuum_full)	{		GistVacuum	gv;		ArrayTuple	res;		LockRelation(rel, AccessExclusiveLock);		gv.index = rel;		initGISTstate(&(gv.giststate), rel);		gv.opCtx = createTempGistContext();		gv.result = stats;		/* walk through the entire index for update tuples */		res = gistVacuumUpdate(&gv, GIST_ROOT_BLKNO, false);		/* cleanup */		if (res.itup)		{			int			i;			for (i = 0; i < res.ituplen; i++)				pfree(res.itup[i]);			pfree(res.itup);		}		freeGISTstate(&(gv.giststate));		MemoryContextDelete(gv.opCtx);	}	else if (needFullVacuum)		ereport(NOTICE,				(errmsg("index \"%s\" needs VACUUM FULL or REINDEX to finish crash recovery",						RelationGetRelationName(rel))));	needFullVacuum = false;	needLock = !RELATION_IS_LOCAL(rel);	if (info->vacuum_full)		needLock = false;		/* relation locked with AccessExclusiveLock */	/* try to find deleted pages */	if (needLock)		LockRelationForExtension(rel, ExclusiveLock);	npages = RelationGetNumberOfBlocks(rel);	if (needLock)		UnlockRelationForExtension(rel, ExclusiveLock);	maxFreePages = npages;	if (maxFreePages > MaxFSMPages)		maxFreePages = MaxFSMPages;	nFreePages = 0;	freePages = (BlockNumber *) palloc(sizeof(BlockNumber) * maxFreePages);	for (blkno = GIST_ROOT_BLKNO + 1; blkno < npages; blkno++)	{		Buffer		buffer;		Page		page;		vacuum_delay_point();		buffer = ReadBuffer(rel, blkno);		LockBuffer(buffer, GIST_SHARE);		page = (Page) BufferGetPage(buffer);		if (GistPageIsDeleted(page))		{			if (nFreePages < maxFreePages)			{				freePages[nFreePages] = blkno;				nFreePages++;			}		}		else			lastFilledBlock = blkno;		LockBuffer(buffer, GIST_UNLOCK);		ReleaseBuffer(buffer);	}	lastBlock = npages - 1;	if (info->vacuum_full && nFreePages > 0)	{							/* try to truncate index */		int			i;		for (i = 0; i < nFreePages; i++)			if (freePages[i] >= lastFilledBlock)			{				nFreePages = i;				break;			}		if (lastBlock > lastFilledBlock)			RelationTruncate(rel, lastFilledBlock + 1);		stats->pages_removed = lastBlock - lastFilledBlock;	}	RecordIndexFreeSpace(&rel->rd_node, nFreePages, freePages);	pfree(freePages);	/* return statistics */	stats->pages_free = nFreePages;	if (needLock)		LockRelationForExtension(rel, ExclusiveLock);	stats->num_pages = RelationGetNumberOfBlocks(rel);	if (needLock)		UnlockRelationForExtension(rel, ExclusiveLock);	if (info->vacuum_full)		UnlockRelation(rel, AccessExclusiveLock);	PG_RETURN_POINTER(stats);}typedef struct GistBDItem{	GistNSN		parentlsn;	BlockNumber blkno;	struct GistBDItem *next;} GistBDItem;static voidpushStackIfSplited(Page page, GistBDItem *stack){	GISTPageOpaque opaque = GistPageGetOpaque(page);	if (stack->blkno != GIST_ROOT_BLKNO && !XLogRecPtrIsInvalid(stack->parentlsn) &&		XLByteLT(stack->parentlsn, opaque->nsn) &&		opaque->rightlink != InvalidBlockNumber /* sanity check */ )	{		/* split page detected, install right link to the stack */		GistBDItem *ptr = (GistBDItem *) palloc(sizeof(GistBDItem));		ptr->blkno = opaque->rightlink;		ptr->parentlsn = stack->parentlsn;		ptr->next = stack->next;		stack->next = ptr;	}}/* * Bulk deletion of all index entries pointing to a set of heap tuples and * check invalid tuples after crash recovery. * The set of target tuples is specified via a callback routine that tells * whether any given heap tuple (identified by ItemPointer) is being deleted. * * Result: a palloc'd struct containing statistical info for VACUUM displays. */Datumgistbulkdelete(PG_FUNCTION_ARGS){	Relation	rel = (Relation) PG_GETARG_POINTER(0);	IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);	void	   *callback_state = (void *) PG_GETARG_POINTER(2);	IndexBulkDeleteResult *result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));	GistBDItem *stack,			   *ptr;	bool		needLock;	stack = (GistBDItem *) palloc0(sizeof(GistBDItem));	stack->blkno = GIST_ROOT_BLKNO;	needFullVacuum = false;	while (stack)	{		Buffer		buffer = ReadBuffer(rel, stack->blkno);		Page		page;		OffsetNumber i,					maxoff;		IndexTuple	idxtuple;		ItemId		iid;		LockBuffer(buffer, GIST_SHARE);		page = (Page) BufferGetPage(buffer);		if (GistPageIsLeaf(page))		{			OffsetNumber todelete[MaxOffsetNumber];			int			ntodelete = 0;			LockBuffer(buffer, GIST_UNLOCK);			LockBuffer(buffer, GIST_EXCLUSIVE);			page = (Page) BufferGetPage(buffer);			if (stack->blkno == GIST_ROOT_BLKNO && !GistPageIsLeaf(page))			{				/* only the root can become non-leaf during relock */				LockBuffer(buffer, GIST_UNLOCK);				ReleaseBuffer(buffer);				/* one more check */				continue;			}			/*			 * check for split proceeded after look at parent, we should check			 * it after relock			 */			pushStackIfSplited(page, stack);			maxoff = PageGetMaxOffsetNumber(page);			for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))			{				iid = PageGetItemId(page, i);				idxtuple = (IndexTuple) PageGetItem(page, iid);				if (callback(&(idxtuple->t_tid), callback_state))				{					PageIndexTupleDelete(page, i);					todelete[ntodelete] = i;					i--;					maxoff--;					ntodelete++;					result->tuples_removed += 1;					Assert(maxoff == PageGetMaxOffsetNumber(page));				}				else					result->num_index_tuples += 1;			}			if (ntodelete)			{				GistMarkTuplesDeleted(page);				if (!rel->rd_istemp)				{					XLogRecData *rdata;					XLogRecPtr	recptr;					gistxlogEntryUpdate *xlinfo;					rdata = formUpdateRdata(rel->rd_node, stack->blkno, todelete, ntodelete,											false, NULL, 0, NULL);					xlinfo = (gistxlogEntryUpdate *) rdata->data;					START_CRIT_SECTION();					recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_ENTRY_UPDATE, rdata);					PageSetLSN(page, recptr);					PageSetTLI(page, ThisTimeLineID);					END_CRIT_SECTION();					pfree(xlinfo);					pfree(rdata);				}				else					PageSetLSN(page, XLogRecPtrForTemp);				WriteNoReleaseBuffer(buffer);			}		}		else		{			/* check for split proceeded after look at parent */			pushStackIfSplited(page, stack);			maxoff = PageGetMaxOffsetNumber(page);			for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))			{				iid = PageGetItemId(page, i);				idxtuple = (IndexTuple) PageGetItem(page, iid);				ptr = (GistBDItem *) palloc(sizeof(GistBDItem));				ptr->blkno = ItemPointerGetBlockNumber(&(idxtuple->t_tid));				ptr->parentlsn = PageGetLSN(page);				ptr->next = stack->next;				stack->next = ptr;				if (GistTupleIsInvalid(idxtuple))					needFullVacuum = true;			}		}		LockBuffer(buffer, GIST_UNLOCK);		ReleaseBuffer(buffer);		ptr = stack->next;		pfree(stack);		stack = ptr;		vacuum_delay_point();	}	needLock = !RELATION_IS_LOCAL(rel);	if (needLock)		LockRelationForExtension(rel, ExclusiveLock);	result->num_pages = RelationGetNumberOfBlocks(rel);	if (needLock)		UnlockRelationForExtension(rel, ExclusiveLock);	PG_RETURN_POINTER(result);}

⌨️ 快捷键说明

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