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

📄 vacuum.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 5 页
字号:
			func_operator = oper("=", stats->attr->atttypid, stats->attr->atttypid, true);			if (func_operator != NULL)			{				pgopform = (Form_pg_operator) GETSTRUCT(func_operator);				fmgr_info(pgopform->oprcode, &(stats->f_cmpeq));			}			else				stats->f_cmpeq.fn_addr = NULL;			func_operator = oper("<", stats->attr->atttypid, stats->attr->atttypid, true);			if (func_operator != NULL)			{				pgopform = (Form_pg_operator) GETSTRUCT(func_operator);				fmgr_info(pgopform->oprcode, &(stats->f_cmplt));			}			else				stats->f_cmplt.fn_addr = NULL;			func_operator = oper(">", stats->attr->atttypid, stats->attr->atttypid, true);			if (func_operator != NULL)			{				pgopform = (Form_pg_operator) GETSTRUCT(func_operator);				fmgr_info(pgopform->oprcode, &(stats->f_cmpgt));			}			else				stats->f_cmpgt.fn_addr = NULL;			typetuple = SearchSysCacheTuple(TYPOID,								 ObjectIdGetDatum(stats->attr->atttypid),											0, 0, 0);			if (HeapTupleIsValid(typetuple))				stats->outfunc = ((Form_pg_type) GETSTRUCT(typetuple))->typoutput;			else				stats->outfunc = InvalidOid;		}		vacrelstats->va_natts = attr_cnt;		vc_delhilowstats(relid, ((attnums) ? attr_cnt : 0), attnums);		if (attnums)			pfree(attnums);	}	else	{		vacrelstats->va_natts = 0;		vacrelstats->vacattrstats = (VacAttrStats *) NULL;	}	/* we require the relation to be locked until the indices are cleaned */	LockRelation(onerel, AccessExclusiveLock);	GetXmaxRecent(&XmaxRecent);	/* scan it */	vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;	vc_scanheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);	/* Now open indices */	Irel = (Relation *) NULL;	vc_getindices(vacrelstats->relid, &nindices, &Irel);	if (nindices > 0)		vacrelstats->hasindex = true;	else		vacrelstats->hasindex = false;	/* Clean/scan index relation(s) */	if (Irel != (Relation *) NULL)	{		if (vacuum_pages.vpl_num_pages > 0)		{			for (i = 0; i < nindices; i++)				vc_vaconeind(&vacuum_pages, Irel[i], vacrelstats->num_tuples, 0);		}		else/* just scan indices to update statistic */		{			for (i = 0; i < nindices; i++)				vc_scanoneind(Irel[i], vacrelstats->num_tuples);		}	}	if (fraged_pages.vpl_num_pages > 0) /* Try to shrink heap */		vc_rpfheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel);	else	{		if (Irel != (Relation *) NULL)			vc_clsindices(nindices, Irel);		if (vacuum_pages.vpl_num_pages > 0)		/* Clean pages from												 * vacuum_pages list */			vc_vacheap(vacrelstats, onerel, &vacuum_pages);	}	/* ok - free vacuum_pages list of reapped pages */	if (vacuum_pages.vpl_num_pages > 0)	{		vpp = vacuum_pages.vpl_pagedesc;		for (i = 0; i < vacuum_pages.vpl_num_pages; i++, vpp++)			pfree(*vpp);		pfree(vacuum_pages.vpl_pagedesc);		if (fraged_pages.vpl_num_pages > 0)			pfree(fraged_pages.vpl_pagedesc);	}	/* all done with this class */	heap_close(onerel);	/* update statistics in pg_class */	vc_updstats(vacrelstats->relid, vacrelstats->num_pages,			vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);	/* next command frees attribute stats */	CommitTransactionCommand();}/* *	vc_scanheap() -- scan an open heap relation * *		This routine sets commit times, constructs vacuum_pages list of *		empty/uninitialized pages and pages with dead tuples and *		~LP_USED line pointers, constructs fraged_pages list of pages *		appropriate for purposes of shrinking and maintains statistics *		on the number of live tuples in a heap. */static voidvc_scanheap(VRelStats *vacrelstats, Relation onerel,			VPageList vacuum_pages, VPageList fraged_pages){	int			nblocks,				blkno;	ItemId		itemid;	Buffer		buf;	HeapTupleData tuple;	Page		page,				tempPage = NULL;	OffsetNumber offnum,				maxoff;	bool		pgchanged,				tupgone,				dobufrel,				notup;	char	   *relname;	VPageDescr	vpc,				vp;	uint32		tups_vacuumed,				num_tuples,				nkeep,				nunused,				ncrash,				empty_pages,				new_pages,				changed_pages,				empty_end_pages;	Size		free_size,				usable_free_size;	Size		min_tlen = MaxTupleSize;	Size		max_tlen = 0;	int32		i;	struct rusage ru0,				ru1;	bool		do_shrinking = true;	VTupleLink	vtlinks = (VTupleLink) palloc(100 * sizeof(VTupleLinkData));	int			num_vtlinks = 0;	int			free_vtlinks = 100;	getrusage(RUSAGE_SELF, &ru0);	relname = (RelationGetRelationName(onerel))->data;	elog(MESSAGE_LEVEL, "--Relation %s--", relname);	tups_vacuumed = num_tuples = nkeep = nunused = ncrash = empty_pages =		new_pages = changed_pages = empty_end_pages = 0;	free_size = usable_free_size = 0;	nblocks = RelationGetNumberOfBlocks(onerel);	vpc = (VPageDescr) palloc(sizeof(VPageDescrData) + MaxOffsetNumber * sizeof(OffsetNumber));	vpc->vpd_offsets_used = 0;	for (blkno = 0; blkno < nblocks; blkno++)	{		buf = ReadBuffer(onerel, blkno);		page = BufferGetPage(buf);		vpc->vpd_blkno = blkno;		vpc->vpd_offsets_free = 0;		if (PageIsNew(page))		{			elog(NOTICE, "Rel %s: Uninitialized page %u - fixing",				 relname, blkno);			PageInit(page, BufferGetPageSize(buf), 0);			vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;			free_size += (vpc->vpd_free - sizeof(ItemIdData));			new_pages++;			empty_end_pages++;			vc_reappage(vacuum_pages, vpc);			WriteBuffer(buf);			continue;		}		if (PageIsEmpty(page))		{			vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;			free_size += (vpc->vpd_free - sizeof(ItemIdData));			empty_pages++;			empty_end_pages++;			vc_reappage(vacuum_pages, vpc);			ReleaseBuffer(buf);			continue;		}		pgchanged = false;		notup = true;		maxoff = PageGetMaxOffsetNumber(page);		for (offnum = FirstOffsetNumber;			 offnum <= maxoff;			 offnum = OffsetNumberNext(offnum))		{			itemid = PageGetItemId(page, offnum);			/*			 * Collect un-used items too - it's possible to have indices			 * pointing here after crash.			 */			if (!ItemIdIsUsed(itemid))			{				vpc->vpd_offsets[vpc->vpd_offsets_free++] = offnum;				nunused++;				continue;			}			tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);			tuple.t_len = ItemIdGetLength(itemid);			ItemPointerSet(&(tuple.t_self), blkno, offnum);			tupgone = false;			if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))			{				if (tuple.t_data->t_infomask & HEAP_XMIN_INVALID)					tupgone = true;				else if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)				{					if (TransactionIdDidCommit((TransactionId)											   tuple.t_data->t_cmin))					{						tuple.t_data->t_infomask |= HEAP_XMIN_INVALID;						tupgone = true;					}					else					{						tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED;						pgchanged = true;					}				}				else if (tuple.t_data->t_infomask & HEAP_MOVED_IN)				{					if (!TransactionIdDidCommit((TransactionId)												tuple.t_data->t_cmin))					{						tuple.t_data->t_infomask |= HEAP_XMIN_INVALID;						tupgone = true;					}					else					{						tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED;						pgchanged = true;					}				}				else				{					if (TransactionIdDidAbort(tuple.t_data->t_xmin))						tupgone = true;					else if (TransactionIdDidCommit(tuple.t_data->t_xmin))					{						tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED;						pgchanged = true;					}					else if (!TransactionIdIsInProgress(tuple.t_data->t_xmin))					{						/*						 * Not Aborted, Not Committed, Not in Progress -						 * so it's from crashed process. - vadim 11/26/96						 */						ncrash++;						tupgone = true;					}					else					{						elog(NOTICE, "Rel %s: TID %u/%u: InsertTransactionInProgress %u - can't shrink relation",						   relname, blkno, offnum, tuple.t_data->t_xmin);						do_shrinking = false;					}				}			}			/*			 * here we are concerned about tuples with xmin committed and			 * xmax unknown or committed			 */			if (tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED &&				!(tuple.t_data->t_infomask & HEAP_XMAX_INVALID))			{				if (tuple.t_data->t_infomask & HEAP_XMAX_COMMITTED)				{					if (tuple.t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)					{						pgchanged = true;						tuple.t_data->t_infomask |= HEAP_XMAX_INVALID;					}					else						tupgone = true;				}				else if (TransactionIdDidAbort(tuple.t_data->t_xmax))				{					tuple.t_data->t_infomask |= HEAP_XMAX_INVALID;					pgchanged = true;				}				else if (TransactionIdDidCommit(tuple.t_data->t_xmax))				{					if (tuple.t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)					{						tuple.t_data->t_infomask |= HEAP_XMAX_INVALID;						pgchanged = true;					}					else						tupgone = true;				}				else if (!TransactionIdIsInProgress(tuple.t_data->t_xmax))				{					/*					 * Not Aborted, Not Committed, Not in Progress - so it					 * from crashed process. - vadim 06/02/97					 */					tuple.t_data->t_infomask |= HEAP_XMAX_INVALID;					pgchanged = true;				}				else				{					elog(NOTICE, "Rel %s: TID %u/%u: DeleteTransactionInProgress %u - can't shrink relation",						 relname, blkno, offnum, tuple.t_data->t_xmax);					do_shrinking = false;				}				/*				 * If tuple is recently deleted then we must not remove it				 * from relation.				 */				if (tupgone && tuple.t_data->t_xmax >= XmaxRecent)				{					tupgone = false;					nkeep++;					if (!(tuple.t_data->t_infomask & HEAP_XMAX_COMMITTED))					{						tuple.t_data->t_infomask |= HEAP_XMAX_COMMITTED;						pgchanged = true;					}					/*					 * If we do shrinking and this tuple is updated one					 * then remember it to construct updated tuple					 * dependencies.					 */					if (do_shrinking && !(ItemPointerEquals(&(tuple.t_self),											   &(tuple.t_data->t_ctid))))					{						if (free_vtlinks == 0)						{							free_vtlinks = 1000;							vtlinks = (VTupleLink) repalloc(vtlinks,										   (free_vtlinks + num_vtlinks) *												 sizeof(VTupleLinkData));						}						vtlinks[num_vtlinks].new_tid = tuple.t_data->t_ctid;						vtlinks[num_vtlinks].this_tid = tuple.t_self;						free_vtlinks--;						num_vtlinks++;					}				}			}			/*			 * Other checks...			 */			if (!OidIsValid(tuple.t_data->t_oid))			{				elog(NOTICE, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.",					 relname, blkno, offnum, tupgone);			}			if (tupgone)			{				ItemId		lpp;				if (tempPage == (Page) NULL)				{					Size		pageSize;					pageSize = PageGetPageSize(page);					tempPage = (Page) palloc(pageSize);					memmove(tempPage, page, pageSize);				}				lpp = &(((PageHeader) tempPage)->pd_linp[offnum - 1]);				/* mark it unused */				lpp->lp_flags &= ~LP_USED;				vpc->vpd_offsets[vpc->vpd_offsets_free++] = offnum;				tups_vacuumed++;			}			else			{				num_tuples++;				notup = false;				if (tuple.t_len < min_tlen)					min_tlen = tuple.t_len;				if (tuple.t_len > max_tlen)					max_tlen = tuple.t_len;				vc_attrstats(onerel, vacrelstats, &tuple);			}		}		if (pgchanged)		{			WriteBuffer(buf);			dobufrel = false;			changed_pages++;		}		else			dobufrel = true;		if (tempPage != (Page) NULL)		{						/* Some tuples are gone */			PageRepairFragmentation(tempPage);			vpc->vpd_free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;			free_size += vpc->vpd_free;			vc_reappage(vacuum_pages, vpc);			pfree(tempPage);			tempPage = (Page) NULL;		}		else if (vpc->vpd_offsets_free > 0)		{						/* there are only ~LP_USED line pointers */			vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;			free_size += vpc->vpd_free;			vc_reappage(vacuum_pages, vpc);		}		if (dobufrel)			ReleaseBuffer(buf);		if (notup)			empty_end_pages++;		else			empty_end_pages = 0;	}	pfree(vpc);	/* save stats in the rel list for use later */	vacrelstats->num_tuples = num_tuples;	vacrelstats->num_pages = nblocks;/*	  vacrelstats->natts = attr_cnt;*/	if (num_tuples == 0)

⌨️ 快捷键说明

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