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

📄 relcache.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));	if (amstrategies > 0)		operator = (Oid *)			MemoryContextAllocZero(indexcxt,								   natts * amstrategies * sizeof(Oid));	else		operator = NULL;	if (amsupport > 0)	{		int			nsupport = natts * amsupport;		support = (RegProcedure *)			MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));		supportinfo = (FmgrInfo *)			MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));	}	else	{		support = NULL;		supportinfo = NULL;	}	relation->rd_operator = operator;	relation->rd_support = support;	relation->rd_supportinfo = supportinfo;	/*	 * Fill the operator and support procedure OID arrays.	(aminfo and	 * supportinfo are left as zeroes, and are filled on-the-fly when used)	 */	IndexSupportInitialize(relation->rd_indclass,						   operator, support,						   amstrategies, amsupport, natts);	/*	 * expressions and predicate cache will be filled later	 */	relation->rd_indexprs = NIL;	relation->rd_indpred = NIL;}/* * IndexSupportInitialize *		Initializes an index's cached opclass information, *		given the index's pg_index.indclass entry. * * Data is returned into *indexOperator and *indexSupport, which are arrays * allocated by the caller. * * The caller also passes maxStrategyNumber, maxSupportNumber, and * maxAttributeNumber, since these indicate the size of the arrays * it has allocated --- but in practice these numbers must always match * those obtainable from the system catalog entries for the index and * access method. */static voidIndexSupportInitialize(oidvector *indclass,					   Oid *indexOperator,					   RegProcedure *indexSupport,					   StrategyNumber maxStrategyNumber,					   StrategyNumber maxSupportNumber,					   AttrNumber maxAttributeNumber){	int			attIndex;	for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)	{		OpClassCacheEnt *opcentry;		if (!OidIsValid(indclass->values[attIndex]))			elog(ERROR, "bogus pg_index tuple");		/* look up the info for this opclass, using a cache */		opcentry = LookupOpclassInfo(indclass->values[attIndex],									 maxStrategyNumber,									 maxSupportNumber);		/* copy cached data into relcache entry */		if (maxStrategyNumber > 0)			memcpy(&indexOperator[attIndex * maxStrategyNumber],				   opcentry->operatorOids,				   maxStrategyNumber * sizeof(Oid));		if (maxSupportNumber > 0)			memcpy(&indexSupport[attIndex * maxSupportNumber],				   opcentry->supportProcs,				   maxSupportNumber * sizeof(RegProcedure));	}}/* * LookupOpclassInfo * * This routine maintains a per-opclass cache of the information needed * by IndexSupportInitialize().  This is more efficient than relying on * the catalog cache, because we can load all the info about a particular * opclass in a single indexscan of pg_amproc or pg_amop. * * The information from pg_am about expected range of strategy and support * numbers is passed in, rather than being looked up, mainly because the * caller will have it already. * * XXX There isn't any provision for flushing the cache.  However, there * isn't any provision for flushing relcache entries when opclass info * changes, either :-( */static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,				  StrategyNumber numStrats,				  StrategyNumber numSupport){	OpClassCacheEnt *opcentry;	bool		found;	Relation	rel;	SysScanDesc scan;	ScanKeyData skey[2];	HeapTuple	htup;	bool		indexOK;	if (OpClassCache == NULL)	{		/* First time through: initialize the opclass cache */		HASHCTL		ctl;		if (!CacheMemoryContext)			CreateCacheMemoryContext();		MemSet(&ctl, 0, sizeof(ctl));		ctl.keysize = sizeof(Oid);		ctl.entrysize = sizeof(OpClassCacheEnt);		ctl.hash = oid_hash;		OpClassCache = hash_create("Operator class cache", 64,								   &ctl, HASH_ELEM | HASH_FUNCTION);	}	opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,											   (void *) &operatorClassOid,											   HASH_ENTER, &found);	if (found && opcentry->valid)	{		/* Already made an entry for it */		Assert(numStrats == opcentry->numStrats);		Assert(numSupport == opcentry->numSupport);		return opcentry;	}	/* Need to fill in new entry */	opcentry->valid = false;	/* until known OK */	opcentry->numStrats = numStrats;	opcentry->numSupport = numSupport;	if (numStrats > 0)		opcentry->operatorOids = (Oid *)			MemoryContextAllocZero(CacheMemoryContext,								   numStrats * sizeof(Oid));	else		opcentry->operatorOids = NULL;	if (numSupport > 0)		opcentry->supportProcs = (RegProcedure *)			MemoryContextAllocZero(CacheMemoryContext,								   numSupport * sizeof(RegProcedure));	else		opcentry->supportProcs = NULL;	/*	 * To avoid infinite recursion during startup, force heap scans if we're	 * looking up info for the opclasses used by the indexes we would like to	 * reference here.	 */	indexOK = criticalRelcachesBuilt ||		(operatorClassOid != OID_BTREE_OPS_OID &&		 operatorClassOid != INT2_BTREE_OPS_OID);	/*	 * Scan pg_amop to obtain operators for the opclass.  We only fetch the	 * default ones (those with subtype zero).	 */	if (numStrats > 0)	{		ScanKeyInit(&skey[0],					Anum_pg_amop_amopclaid,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(operatorClassOid));		ScanKeyInit(&skey[1],					Anum_pg_amop_amopsubtype,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(InvalidOid));		rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock);		scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK,								  SnapshotNow, 2, skey);		while (HeapTupleIsValid(htup = systable_getnext(scan)))		{			Form_pg_amop amopform = (Form_pg_amop) GETSTRUCT(htup);			if (amopform->amopstrategy <= 0 ||				(StrategyNumber) amopform->amopstrategy > numStrats)				elog(ERROR, "invalid amopstrategy number %d for opclass %u",					 amopform->amopstrategy, operatorClassOid);			opcentry->operatorOids[amopform->amopstrategy - 1] =				amopform->amopopr;		}		systable_endscan(scan);		heap_close(rel, AccessShareLock);	}	/*	 * Scan pg_amproc to obtain support procs for the opclass.	We only fetch	 * the default ones (those with subtype zero).	 */	if (numSupport > 0)	{		ScanKeyInit(&skey[0],					Anum_pg_amproc_amopclaid,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(operatorClassOid));		ScanKeyInit(&skey[1],					Anum_pg_amproc_amprocsubtype,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(InvalidOid));		rel = heap_open(AccessMethodProcedureRelationId, AccessShareLock);		scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,								  SnapshotNow, 2, skey);		while (HeapTupleIsValid(htup = systable_getnext(scan)))		{			Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);			if (amprocform->amprocnum <= 0 ||				(StrategyNumber) amprocform->amprocnum > numSupport)				elog(ERROR, "invalid amproc number %d for opclass %u",					 amprocform->amprocnum, operatorClassOid);			opcentry->supportProcs[amprocform->amprocnum - 1] =				amprocform->amproc;		}		systable_endscan(scan);		heap_close(rel, AccessShareLock);	}	opcentry->valid = true;	return opcentry;}/* *		formrdesc * *		This is a special cut-down version of RelationBuildDesc() *		used by RelationCacheInitialize() in initializing the relcache. *		The relation descriptor is built just from the supplied parameters, *		without actually looking at any system table entries.  We cheat *		quite a lot since we only need to work for a few basic system *		catalogs. * * formrdesc is currently used for: pg_class, pg_attribute, pg_proc, * and pg_type (see RelationCacheInitialize). * * Note that these catalogs can't have constraints (except attnotnull), * default values, rules, or triggers, since we don't cope with any of that. * * NOTE: we assume we are already switched into CacheMemoryContext. */static voidformrdesc(const char *relationName, Oid relationReltype,		  bool hasoids, int natts, FormData_pg_attribute *att){	Relation	relation;	int			i;	bool		has_not_null;	/*	 * allocate new relation desc, clear all fields of reldesc	 */	relation = (Relation) palloc0(sizeof(RelationData));	relation->rd_targblock = InvalidBlockNumber;	/* make sure relation is marked as having no open file yet */	relation->rd_smgr = NULL;	/*	 * initialize reference count: 1 because it is nailed in cache	 */	relation->rd_refcnt = 1;	/*	 * all entries built with this routine are nailed-in-cache; none are for	 * new or temp relations.	 */	relation->rd_isnailed = true;	relation->rd_createSubid = InvalidSubTransactionId;	relation->rd_istemp = false;	/*	 * initialize relation tuple form	 *	 * The data we insert here is pretty incomplete/bogus, but it'll serve to	 * get us launched.  RelationCacheInitializePhase2() will read the real	 * data from pg_class and replace what we've done here.	 */	relation->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);	namestrcpy(&relation->rd_rel->relname, relationName);	relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;	relation->rd_rel->reltype = relationReltype;	/*	 * It's important to distinguish between shared and non-shared relations,	 * even at bootstrap time, to make sure we know where they are stored.	At	 * present, all relations that formrdesc is used for are not shared.	 */	relation->rd_rel->relisshared = false;	relation->rd_rel->relpages = 1;	relation->rd_rel->reltuples = 1;	relation->rd_rel->relkind = RELKIND_RELATION;	relation->rd_rel->relhasoids = hasoids;	relation->rd_rel->relnatts = (int16) natts;	/*	 * initialize attribute tuple form	 *	 * Unlike the case with the relation tuple, this data had better be right	 * because it will never be replaced.  The input values must be correctly	 * defined by macros in src/include/catalog/ headers.	 */	relation->rd_att = CreateTemplateTupleDesc(natts, hasoids);	relation->rd_att->tdtypeid = relationReltype;	relation->rd_att->tdtypmod = -1;	/* unnecessary, but... */	/*	 * initialize tuple desc info	 */	has_not_null = false;	for (i = 0; i < natts; i++)	{		memcpy(relation->rd_att->attrs[i],			   &att[i],			   ATTRIBUTE_TUPLE_SIZE);		has_not_null |= att[i].attnotnull;		/* make sure attcacheoff is valid */		relation->rd_att->attrs[i]->attcacheoff = -1;	}	/* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */	relation->rd_att->attrs[0]->attcacheoff = 0;	/* mark not-null status */	if (has_not_null)	{		TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));		constr->has_not_null = true;		relation->rd_att->constr = constr;	}	/*	 * initialize relation id from info in att array (my, this is ugly)	 */	RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;	relation->rd_rel->relfilenode = RelationGetRelid(relation);	/*	 * initialize the relation lock manager information	 */	RelationInitLockInfo(relation);		/* see lmgr.c */	/*	 * initialize physical addressing information for the relation	 */	RelationInitPhysicalAddr(relation);	/*	 * initialize the rel-has-index flag, using hardwired knowledge	 */	if (IsBootstrapProcessingMode())	{		/* In bootstrap mode, we have no indexes */		relation->rd_rel->relhasindex = false;	}	else	{		/* Otherwise, all the rels formrdesc is used for have indexes */		relation->rd_rel->relhasindex = true;	}	/*	 * add new reldesc to relcache	 */	RelationCacheInsert(relation);	/* It's fully valid */	relation->rd_isvalid = true;}/* ---------------------------------------------------------------- *				 Relation Descriptor Lookup Interface * ---------------------------------------------------------------- *//* *		RelationIdCacheGetRelation * *		Lookup an existing reldesc by OID. * *		Only try to get the reldesc by looking in the cache, *		do not go to the disk if it's not present. * *		NB: relation ref count is incremented if successful. *		Caller should eventually decrement count.  (Usually, *		that happens by calling RelationClose().) */RelationRelationIdCacheGetRelation(Oid relationId){	Relation	rd;	RelationIdCacheLookup(relationId, rd);	if (RelationIsValid(rd))	{		RelationIncrementReferenceCount(rd);		/* revalidate nailed index if necessary */		if (!rd->rd_isvalid)			RelationReloadClassinfo(rd);	}	return rd;}/* *		RelationIdGetRelation * *		Lookup a reldesc by OID; make one if not already in cache. * *		NB: relation ref count is incremented, or set to 1 if new entry. *		Caller should eventually decrement count.  (Usually, *		that happens by calling RelationClose().) */RelationRelationIdGetRelation(Oid relationId){	Relation	rd;

⌨️ 快捷键说明

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