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

📄 relcache.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
					rebuildFirstList = lcons(relation, rebuildFirstList);				else					rebuildFirstList = lappend(rebuildFirstList, relation);			}			else				rebuildList = lcons(relation, rebuildList);		}	}	/*	 * Now zap any remaining smgr cache entries.  This must happen before we	 * start to rebuild entries, since that may involve catalog fetches which	 * will re-open catalog files.	 */	smgrcloseall();	/* Phase 2: rebuild the items found to need rebuild in phase 1 */	foreach(l, rebuildFirstList)	{		relation = (Relation) lfirst(l);		RelationClearRelation(relation, true);	}	list_free(rebuildFirstList);	foreach(l, rebuildList)	{		relation = (Relation) lfirst(l);		RelationClearRelation(relation, true);	}	list_free(rebuildList);}/* * AtEOXact_RelationCache * *	Clean up the relcache at main-transaction commit or abort. * * Note: this must be called *before* processing invalidation messages. * In the case of abort, we don't want to try to rebuild any invalidated * cache entries (since we can't safely do database accesses).  Therefore * we must reset refcnts before handling pending invalidations. * * As of PostgreSQL 8.1, relcache refcnts should get released by the * ResourceOwner mechanism.  This routine just does a debugging * cross-check that no pins remain.  However, we also need to do special * cleanup when the current transaction created any relations or made use * of forced index lists. */voidAtEOXact_RelationCache(bool isCommit){	HASH_SEQ_STATUS status;	RelIdCacheEnt *idhentry;	/*	 * To speed up transaction exit, we want to avoid scanning the relcache	 * unless there is actually something for this routine to do.  Other than	 * the debug-only Assert checks, most transactions don't create any work	 * for us to do here, so we keep a static flag that gets set if there is	 * anything to do.	(Currently, this means either a relation is created in	 * the current xact, or an index list is forced.)  For simplicity, the	 * flag remains set till end of top-level transaction, even though we	 * could clear it at subtransaction end in some cases.	 */	if (!need_eoxact_work#ifdef USE_ASSERT_CHECKING		&& !assert_enabled#endif		)		return;	hash_seq_init(&status, RelationIdCache);	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)	{		Relation	relation = idhentry->reldesc;		/*		 * The relcache entry's ref count should be back to its normal		 * not-in-a-transaction state: 0 unless it's nailed in cache.		 *		 * In bootstrap mode, this is NOT true, so don't check it --- the		 * bootstrap code expects relations to stay open across start/commit		 * transaction calls.  (That seems bogus, but it's not worth fixing.)		 */#ifdef USE_ASSERT_CHECKING		if (!IsBootstrapProcessingMode())		{			int			expected_refcnt;			expected_refcnt = relation->rd_isnailed ? 1 : 0;			Assert(relation->rd_refcnt == expected_refcnt);		}#endif		/*		 * Is it a relation created in the current transaction?		 *		 * During commit, reset the flag to zero, since we are now out of the		 * creating transaction.  During abort, simply delete the relcache		 * entry --- it isn't interesting any longer.  (NOTE: if we have		 * forgotten the new-ness of a new relation due to a forced cache		 * flush, the entry will get deleted anyway by shared-cache-inval		 * processing of the aborted pg_class insertion.)		 */		if (relation->rd_createSubid != InvalidSubTransactionId)		{			if (isCommit)				relation->rd_createSubid = InvalidSubTransactionId;			else			{				RelationClearRelation(relation, false);				continue;			}		}		/*		 * Flush any temporary index list.		 */		if (relation->rd_indexvalid == 2)		{			list_free(relation->rd_indexlist);			relation->rd_indexlist = NIL;			relation->rd_oidindex = InvalidOid;			relation->rd_indexvalid = 0;		}	}	/* Once done with the transaction, we can reset need_eoxact_work */	need_eoxact_work = false;}/* * AtEOSubXact_RelationCache * *	Clean up the relcache at sub-transaction commit or abort. * * Note: this must be called *before* processing invalidation messages. */voidAtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid,						  SubTransactionId parentSubid){	HASH_SEQ_STATUS status;	RelIdCacheEnt *idhentry;	/*	 * Skip the relcache scan if nothing to do --- see notes for	 * AtEOXact_RelationCache.	 */	if (!need_eoxact_work)		return;	hash_seq_init(&status, RelationIdCache);	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)	{		Relation	relation = idhentry->reldesc;		/*		 * Is it a relation created in the current subtransaction?		 *		 * During subcommit, mark it as belonging to the parent, instead.		 * During subabort, simply delete the relcache entry.		 */		if (relation->rd_createSubid == mySubid)		{			if (isCommit)				relation->rd_createSubid = parentSubid;			else			{				Assert(RelationHasReferenceCountZero(relation));				RelationClearRelation(relation, false);				continue;			}		}		/*		 * Flush any temporary index list.		 */		if (relation->rd_indexvalid == 2)		{			list_free(relation->rd_indexlist);			relation->rd_indexlist = NIL;			relation->rd_oidindex = InvalidOid;			relation->rd_indexvalid = 0;		}	}}/* *		RelationBuildLocalRelation *			Build a relcache entry for an about-to-be-created relation, *			and enter it into the relcache. */RelationRelationBuildLocalRelation(const char *relname,						   Oid relnamespace,						   TupleDesc tupDesc,						   Oid relid,						   Oid reltablespace,						   bool shared_relation){	Relation	rel;	MemoryContext oldcxt;	int			natts = tupDesc->natts;	int			i;	bool		has_not_null;	bool		nailit;	AssertArg(natts >= 0);	/*	 * check for creation of a rel that must be nailed in cache.	 *	 * XXX this list had better match RelationCacheInitialize's list.	 */	switch (relid)	{		case RelationRelationId:		case AttributeRelationId:		case ProcedureRelationId:		case TypeRelationId:			nailit = true;			break;		default:			nailit = false;			break;	}	/*	 * switch to the cache context to create the relcache entry.	 */	if (!CacheMemoryContext)		CreateCacheMemoryContext();	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);	/*	 * allocate a new relation descriptor and fill in basic state fields.	 */	rel = (Relation) palloc0(sizeof(RelationData));	rel->rd_targblock = InvalidBlockNumber;	/* make sure relation is marked as having no open file yet */	rel->rd_smgr = NULL;	/* mark it nailed if appropriate */	rel->rd_isnailed = nailit;	rel->rd_refcnt = nailit ? 1 : 0;	/* it's being created in this transaction */	rel->rd_createSubid = GetCurrentSubTransactionId();	/* must flag that we have rels created in this transaction */	need_eoxact_work = true;	/* is it a temporary relation? */	rel->rd_istemp = isTempNamespace(relnamespace);	/*	 * create a new tuple descriptor from the one passed in.  We do this	 * partly to copy it into the cache context, and partly because the new	 * relation can't have any defaults or constraints yet; they have to be	 * added in later steps, because they require additions to multiple system	 * catalogs.  We can copy attnotnull constraints here, however.	 */	rel->rd_att = CreateTupleDescCopy(tupDesc);	has_not_null = false;	for (i = 0; i < natts; i++)	{		rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;		has_not_null |= tupDesc->attrs[i]->attnotnull;	}	if (has_not_null)	{		TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));		constr->has_not_null = true;		rel->rd_att->constr = constr;	}	/*	 * initialize relation tuple form (caller may add/override data later)	 */	rel->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);	namestrcpy(&rel->rd_rel->relname, relname);	rel->rd_rel->relnamespace = relnamespace;	rel->rd_rel->relkind = RELKIND_UNCATALOGED;	rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;	rel->rd_rel->relnatts = natts;	rel->rd_rel->reltype = InvalidOid;	/* needed when bootstrapping: */	rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;	/*	 * Insert relation physical and logical identifiers (OIDs) into the right	 * places.	Note that the physical ID (relfilenode) is initially the same	 * as the logical ID (OID).	 */	rel->rd_rel->relisshared = shared_relation;	RelationGetRelid(rel) = relid;	for (i = 0; i < natts; i++)		rel->rd_att->attrs[i]->attrelid = relid;	rel->rd_rel->relfilenode = relid;	rel->rd_rel->reltablespace = reltablespace;	RelationInitLockInfo(rel);	/* see lmgr.c */	RelationInitPhysicalAddr(rel);	/*	 * Okay to insert into the relcache hash tables.	 */	RelationCacheInsert(rel);	/*	 * done building relcache entry.	 */	MemoryContextSwitchTo(oldcxt);	/* It's fully valid */	rel->rd_isvalid = true;	/*	 * Caller expects us to pin the returned entry.	 */	RelationIncrementReferenceCount(rel);	return rel;}/* *		RelationCacheInitialize * *		This initializes the relation descriptor cache.  At the time *		that this is invoked, we can't do database access yet (mainly *		because the transaction subsystem is not up), so we can't get *		"real" info.  However it's okay to read the pg_internal.init *		cache file, if one is available.  Otherwise we make phony *		entries for the minimum set of nailed-in-cache relations. */#define INITRELCACHESIZE		400voidRelationCacheInitialize(void){	MemoryContext oldcxt;	HASHCTL		ctl;	/*	 * switch to cache memory context	 */	if (!CacheMemoryContext)		CreateCacheMemoryContext();	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);	/*	 * create hashtables that index the relcache	 */	MemSet(&ctl, 0, sizeof(ctl));	ctl.keysize = sizeof(Oid);	ctl.entrysize = sizeof(RelIdCacheEnt);	ctl.hash = oid_hash;	RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,								  &ctl, HASH_ELEM | HASH_FUNCTION);	/*	 * Try to load the relcache cache file.  If successful, we're done for	 * now.  Otherwise, initialize the cache with pre-made descriptors for the	 * critical "nailed-in" system catalogs.	 */	if (IsBootstrapProcessingMode() ||		!load_relcache_init_file())	{		formrdesc("pg_class", PG_CLASS_RELTYPE_OID,				  true, Natts_pg_class, Desc_pg_class);		formrdesc("pg_attribute", PG_ATTRIBUTE_RELTYPE_OID,				  false, Natts_pg_attribute, Desc_pg_attribute);		formrdesc("pg_proc", PG_PROC_RELTYPE_OID,				  true, Natts_pg_proc, Desc_pg_proc);		formrdesc("pg_type", PG_TYPE_RELTYPE_OID,				  true, Natts_pg_type, Desc_pg_type);#define NUM_CRITICAL_RELS	4	/* fix if you change list above */	}	MemoryContextSwitchTo(oldcxt);}/* *		RelationCacheInitializePhase2 * *		This is called as soon as the catcache and transaction system *		are functional.  At this point we can actually read data from *		the system catalogs.  Update the relcache entries made during *		RelationCacheInitialize, and make sure we have entries for the *		critical system indexes. */voidRelationCacheInitializePhase2(void){	HASH_SEQ_STATUS status;	RelIdCacheEnt *idhentry;	if (IsBootstrapProcessingMode())		return;	/*	 * If we didn't get the critical system indexes loaded into relcache, do	 * so now.	These are critical because the catcache depends on them for	 * catcache fetches that are done during relcache load.  Thus, we have an	 * infinite-recursion problem.	We can break the recursion by doing	 * heapscans instead of indexscans at certain key spots. To avoid hobbling	 * performance, we only want to do that until we have the critical indexes	 * loaded into relcache.  Thus, the flag criticalRelcachesBuilt is used to	 * decide whether to do heapscan or indexscan at the key spots, and we set	 * it true after we've loaded the critical indexes.	 *	 * The critical indexes are marked as "nailed in cache", partly to make it	 * easy for load_relcache_init_file to count them, but mainly because we	 * cannot flush and rebuild them once we've set criticalRelcachesBuilt to	 * true.  (NOTE: perhaps it would be possible to reload them by	 * temporarily setting criticalRelcachesBuilt to false again.  For now,	 * though, we just nail 'em in.)	 */	if (!criticalRelcachesBuilt)	{		Relation	ird;#define LOAD_CRIT_INDEX(indexoid) \		do { \			ird = RelationBuildDesc((indexoid), NULL); \			ird->rd_isnailed = true; \			ird->rd_refcnt = 1; \		} while (0)		LOAD_CRIT_INDEX(ClassOidIndexId);		LOAD_CRIT_INDEX(AttributeRelidNumIndexId);		LOAD_CRIT_INDEX(IndexRelidIndexI

⌨️ 快捷键说明

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