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

📄 relcache.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
/* -------------------------------- *		RelationIdCacheGetRelation * *		only try to get the reldesc by looking up the cache *		do not go to the disk.	this is used by BlockPrepareFile() *		and RelationIdGetRelation below. * -------------------------------- */RelationRelationIdCacheGetRelation(Oid relationId){	Relation	rd;	RelationIdCacheLookup(relationId, rd);	if (RelationIsValid(rd))	{		if (rd->rd_fd == -1)		{			rd->rd_fd = smgropen(DEFAULT_SMGR, rd);			Assert(rd->rd_fd != -1);		}		RelationIncrementReferenceCount(rd);	}	return rd;}/* -------------------------------- *		RelationNameCacheGetRelation * -------------------------------- */static RelationRelationNameCacheGetRelation(char *relationName){	Relation	rd;	NameData	name;	/*	 * make sure that the name key used for hash lookup is properly	 * null-padded	 */	namestrcpy(&name, relationName);	RelationNameCacheLookup(name.data, rd);	if (RelationIsValid(rd))	{		if (rd->rd_fd == -1)		{			rd->rd_fd = smgropen(DEFAULT_SMGR, rd);			Assert(rd->rd_fd != -1);		}		RelationIncrementReferenceCount(rd);	}	return rd;}/* -------------------------------- *		RelationIdGetRelation * *		return a relation descriptor based on its id. *		return a cached value if possible * -------------------------------- */RelationRelationIdGetRelation(Oid relationId){	Relation	rd;	RelationBuildDescInfo buildinfo;	/* ----------------	 *	increment access statistics	 * ----------------	 */	IncrHeapAccessStat(local_RelationIdGetRelation);	IncrHeapAccessStat(global_RelationIdGetRelation);	/* ----------------	 *	first try and get a reldesc from the cache	 * ----------------	 */	rd = RelationIdCacheGetRelation(relationId);	if (RelationIsValid(rd))		return rd;	/* ----------------	 *	no reldesc in the cache, so have RelationBuildDesc()	 *	build one and add it.	 * ----------------	 */	buildinfo.infotype = INFO_RELID;	buildinfo.i.info_id = relationId;	rd = RelationBuildDesc(buildinfo);	return rd;}/* -------------------------------- *		RelationNameGetRelation * *		return a relation descriptor based on its name. *		return a cached value if possible * -------------------------------- */RelationRelationNameGetRelation(char *relationName){	Relation	rd;	RelationBuildDescInfo buildinfo;	/* ----------------	 *	increment access statistics	 * ----------------	 */	IncrHeapAccessStat(local_RelationNameGetRelation);	IncrHeapAccessStat(global_RelationNameGetRelation);	/* ----------------	 *	first try and get a reldesc from the cache	 * ----------------	 */	rd = RelationNameCacheGetRelation(relationName);	if (RelationIsValid(rd))		return rd;	/* ----------------	 *	no reldesc in the cache, so have RelationBuildDesc()	 *	build one and add it.	 * ----------------	 */	buildinfo.infotype = INFO_RELNAME;	buildinfo.i.info_name = relationName;	rd = RelationBuildDesc(buildinfo);	return rd;}/* ---------------- *		old "getreldesc" interface. * ---------------- */#ifdef NOT_USEDRelationgetreldesc(char *relationName){	/* ----------------	 *	increment access statistics	 * ----------------	 */	IncrHeapAccessStat(local_getreldesc);	IncrHeapAccessStat(global_getreldesc);	return RelationNameGetRelation(relationName);}#endif/* ---------------------------------------------------------------- *				cache invalidation support routines * ---------------------------------------------------------------- *//* -------------------------------- *		RelationClose - close an open relation * -------------------------------- */voidRelationClose(Relation relation){	/* Note: no locking manipulations needed */	RelationDecrementReferenceCount(relation);}/* -------------------------------- * RelationFlushRelation * *	 Actually blows away a relation... RelationFree doesn't do *	 anything anymore. * -------------------------------- */static voidRelationFlushRelation(Relation *relationPtr,					  bool onlyFlushReferenceCountZero){	MemoryContext oldcxt;	Relation	relation = *relationPtr;	if (relation->rd_isnailed)	{		/* this is a nailed special relation for bootstraping */		return;	}	if (!onlyFlushReferenceCountZero ||		RelationHasReferenceCountZero(relation))	{		oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);		/* make sure smgr and lower levels close the relation's files,		 * if they weren't closed already		 */		smgrclose(DEFAULT_SMGR, relation);		RelationCacheDelete(relation);		FreeTupleDesc(relation->rd_att);		SystemCacheRelationFlushed(RelationGetRelid(relation));		FreeTriggerDesc(relation);#ifdef NOT_USED		if (relation->rd_rules)		{			int			j;			for (j = 0; j < relation->rd_rules->numLocks; j++)				pfree(relation->rd_rules->rules[j]);			pfree(relation->rd_rules->rules);			pfree(relation->rd_rules);		}#endif		pfree(RelationGetLockInfo(relation));		pfree(RelationGetForm(relation));		pfree(relation);		MemoryContextSwitchTo(oldcxt);	}}/* -------------------------------- *		RelationForgetRelation - *		   RelationFlushRelation + if the relation is myxactonly then *		   get rid of the relation descriptor from the newly created *		   relation list. * -------------------------------- */voidRelationForgetRelation(Oid rid){	Relation	relation;	RelationIdCacheLookup(rid, relation);	if (PointerIsValid(relation))	{		if (relation->rd_myxactonly)		{			MemoryContext oldcxt;			List	   *curr;			List	   *prev = NIL;			oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);			foreach(curr, newlyCreatedRelns)			{				Relation	reln = lfirst(curr);				Assert(reln != NULL && reln->rd_myxactonly);				if (RelationGetRelid(reln) == rid)					break;				prev = curr;			}			if (curr == NIL)				elog(FATAL, "Local relation %s not found in list",					 (RelationGetRelationName(relation))->data);			if (prev == NIL)				newlyCreatedRelns = lnext(newlyCreatedRelns);			else				lnext(prev) = lnext(curr);			pfree(curr);			MemoryContextSwitchTo(oldcxt);		}		RelationFlushRelation(&relation, false);	}}/* -------------------------------- *		RelationIdInvalidateRelationCacheByRelationId * -------------------------------- */voidRelationIdInvalidateRelationCacheByRelationId(Oid relationId){	Relation	relation;	RelationIdCacheLookup(relationId, relation);	/*	 * "local" relations are invalidated by RelationPurgeLocalRelation.	 * (This is to make LocalBufferSync's life easier: want the descriptor	 * to hang around for a while. In fact, won't we want this for	 * BufferSync also? But I'll leave it for now since I don't want to	 * break anything.) - ay 3/95	 */	if (PointerIsValid(relation) && !relation->rd_myxactonly)	{		/*		 * The boolean onlyFlushReferenceCountZero in RelationFlushReln()		 * should be set to true when we are incrementing the command		 * counter and to false when we are starting a new xaction.  This		 * can be determined by checking the current xaction status.		 */		RelationFlushRelation(&relation, CurrentXactInProgress());	}}#if NOT_USED					/* See comments at line 1304 *//* -------------------------------- *		RelationIdInvalidateRelationCacheByAccessMethodId * *		RelationFlushIndexes is needed for use with HashTableWalk.. * -------------------------------- */static voidRelationFlushIndexes(Relation *r,					 Oid accessMethodId){	Relation	relation = *r;	if (!RelationIsValid(relation))	{		elog(NOTICE, "inval call to RFI");		return;	}	if (relation->rd_rel->relkind == RELKIND_INDEX &&	/* XXX style */		(!OidIsValid(accessMethodId) ||		 relation->rd_rel->relam == accessMethodId))		RelationFlushRelation(&relation, false);}#endifvoidRelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId){#ifdef NOT_USED	/*	 * 25 aug 1992:  mao commented out the ht walk below.  it should be	 * doing the right thing, in theory, but flushing reldescs for index	 * relations apparently doesn't work.  we want to cut 4.0.1, and i	 * don't want to introduce new bugs.  this code never executed before,	 * so i'm turning it off for now.  after the release is cut, i'll fix	 * this up.	 */	HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes,				  accessMethodId);#else	return;#endif}/* * RelationCacheInvalidate * *	 Will blow away either all the cached relation descriptors or *	 those that have a zero reference count. * */voidRelationCacheInvalidate(bool onlyFlushReferenceCountZero){	HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation,				  onlyFlushReferenceCountZero);	/*	 * nailed-in reldescs will still be in the cache... 7 hardwired heaps	 * + 3 hardwired indices == 10 total.	 */	if (!onlyFlushReferenceCountZero)	{		Assert(RelationNameCache->hctl->nkeys == 10);		Assert(RelationIdCache->hctl->nkeys == 10);	}}/* -------------------------------- *		RelationRegisterRelation - *		   register the Relation descriptor of a newly created relation *		   with the relation descriptor Cache. * -------------------------------- */voidRelationRegisterRelation(Relation relation){	MemoryContext oldcxt;	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	if (oldcxt != (MemoryContext) CacheCxt)		elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt");	RelationCacheInsert(relation);	RelationInitLockInfo(relation);	/*	 * we've just created the relation. It is invisible to anyone else	 * before the transaction is committed. Setting rd_myxactonly allows	 * us to use the local buffer manager for select/insert/etc before the	 * end of transaction. (We also need to keep track of relations	 * created during a transaction and does the necessary clean up at the	 * end of the transaction.)				- ay 3/95	 */	relation->rd_myxactonly = TRUE;	newlyCreatedRelns = lcons(relation, newlyCreatedRelns);	MemoryContextSwitchTo(oldcxt);}/* * RelationPurgeLocalRelation - *	  find all the Relation descriptors marked rd_myxactonly and reset them. *	  This should be called at the end of a transaction (commit/abort) when *	  the "local" relations will become visible to others and the multi-user *	  buffer pool should be used. */voidRelationPurgeLocalRelation(bool xactCommitted){	MemoryContext oldcxt;	if (newlyCreatedRelns == NULL)		return;	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	while (newlyCreatedRelns)	{		List	   *l = newlyCreatedRelns;		Relation	reln = lfirst(l);		Assert(reln != NULL && reln->rd_myxactonly);		if (!xactCommitted)		{			/*			 * remove the file if we abort. This is so that files for			 * tables created inside a transaction block get removed.			 */			if (reln->rd_isnoname)			{				if (!(reln->rd_nonameunlinked))				{					smgrunlink(DEFAULT_SMGR, reln);					reln->rd_nonameunlinked = TRUE;				}			}			else				smgrunlink(DEFAULT_SMGR, reln);		}		reln->rd_myxactonly = FALSE;		if (!IsBootstrapProcessingMode())			RelationFlushRelation(&reln, FALSE);		newlyCreatedRelns = lnext(newlyCreatedRelns);		pfree(l);	}	MemoryContextSwitchTo(oldcxt);}/* -------------------------------- *		RelationInitialize * *		This initializes the relation descriptor cache. * -------------------------------- */#define INITRELCACHESIZE		400voidRelationInitialize(void){	MemoryContext oldcxt;	HASHCTL		ctl;	/* ----------------	 *	switch to cache memory context	 * ----------------	 */	if (!CacheCxt)		CacheCxt = CreateGlobalMemory("Cache");	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	/* ----------------	 *	create global caches	 * ----------------	 */	MemSet(&ctl, 0, (int) sizeof(ctl));	ctl.keysize = sizeof(NameData);	ctl.datasize = sizeof(Relation);	RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM);	ctl.keysize = sizeof(Oid);	ctl.hash = tag_hash;	RelationIdCache = hash_create(INITRELCACHESIZE, &ctl,								  HASH_ELEM | HASH_FUNCTION);	/* ----------------	 *	initialize the cache with pre-made relation descriptors	 *	for some of the more important system relations.  These	 *	relations should always be in the cache.	 * ----------------	 */	formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class);	formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute);	formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc);	formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type);	formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable);	formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log);

⌨️ 快捷键说明

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