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

📄 catcache.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
		 * Invalidate *all* CatCLists in this cache; it's too hard to tell		 * which searches might still be correct, so just zap 'em all.		 */		for (elt = DLGetHead(&ccp->cc_lists); elt; elt = nextelt)		{			CatCList   *cl = (CatCList *) DLE_VAL(elt);			nextelt = DLGetSucc(elt);			if (cl->refcount > 0)				cl->dead = true;			else				CatCacheRemoveCList(ccp, cl);		}		/*		 * inspect the proper hash bucket for tuple matches		 */		hashIndex = HASH_INDEX(hashValue, ccp->cc_nbuckets);		for (elt = DLGetHead(&ccp->cc_bucket[hashIndex]); elt; elt = nextelt)		{			CatCTup    *ct = (CatCTup *) DLE_VAL(elt);			nextelt = DLGetSucc(elt);			if (hashValue != ct->hash_value)				continue;		/* ignore non-matching hash values */			if (ct->negative ||				ItemPointerEquals(pointer, &ct->tuple.t_self))			{				if (ct->refcount > 0 ||					(ct->c_list && ct->c_list->refcount > 0))				{					ct->dead = true;					/* list, if any, was marked dead above */					Assert(ct->c_list == NULL || ct->c_list->dead);				}				else					CatCacheRemoveCTup(ccp, ct);				CACHE1_elog(DEBUG2, "CatalogCacheIdInvalidate: invalidated");#ifdef CATCACHE_STATS				ccp->cc_invals++;#endif				/* could be multiple matches, so keep looking! */			}		}		break;					/* need only search this one cache */	}}/* ---------------------------------------------------------------- *					   public functions * ---------------------------------------------------------------- *//* * Standard routine for creating cache context if it doesn't exist yet * * There are a lot of places (probably far more than necessary) that check * whether CacheMemoryContext exists yet and want to create it if not. * We centralize knowledge of exactly how to create it here. */voidCreateCacheMemoryContext(void){	/*	 * Purely for paranoia, check that context doesn't exist; caller probably	 * did so already.	 */	if (!CacheMemoryContext)		CacheMemoryContext = AllocSetContextCreate(TopMemoryContext,												   "CacheMemoryContext",												   ALLOCSET_DEFAULT_MINSIZE,												   ALLOCSET_DEFAULT_INITSIZE,												   ALLOCSET_DEFAULT_MAXSIZE);}/* *		AtEOXact_CatCache * * Clean up catcaches at end of main transaction (either commit or abort) * * As of PostgreSQL 8.1, catcache pins should get released by the * ResourceOwner mechanism.  This routine is just a debugging * cross-check that no pins remain. */voidAtEOXact_CatCache(bool isCommit){#ifdef USE_ASSERT_CHECKING	if (assert_enabled)	{		CatCache   *ccp;		for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)		{			Dlelem	   *elt;			int			i;			/* Check CatCLists */			for (elt = DLGetHead(&ccp->cc_lists); elt; elt = DLGetSucc(elt))			{				CatCList   *cl = (CatCList *) DLE_VAL(elt);				Assert(cl->cl_magic == CL_MAGIC);				Assert(cl->refcount == 0);				Assert(!cl->dead);			}			/* Check individual tuples */			for (i = 0; i < ccp->cc_nbuckets; i++)			{				for (elt = DLGetHead(&ccp->cc_bucket[i]);					 elt;					 elt = DLGetSucc(elt))				{					CatCTup    *ct = (CatCTup *) DLE_VAL(elt);					Assert(ct->ct_magic == CT_MAGIC);					Assert(ct->refcount == 0);					Assert(!ct->dead);				}			}		}	}#endif}/* *		ResetCatalogCache * * Reset one catalog cache to empty. * * This is not very efficient if the target cache is nearly empty. * However, it shouldn't need to be efficient; we don't invoke it often. */static voidResetCatalogCache(CatCache *cache){	Dlelem	   *elt,			   *nextelt;	int			i;	/* Remove each list in this cache, or at least mark it dead */	for (elt = DLGetHead(&cache->cc_lists); elt; elt = nextelt)	{		CatCList   *cl = (CatCList *) DLE_VAL(elt);		nextelt = DLGetSucc(elt);		if (cl->refcount > 0)			cl->dead = true;		else			CatCacheRemoveCList(cache, cl);	}	/* Remove each tuple in this cache, or at least mark it dead */	for (i = 0; i < cache->cc_nbuckets; i++)	{		for (elt = DLGetHead(&cache->cc_bucket[i]); elt; elt = nextelt)		{			CatCTup    *ct = (CatCTup *) DLE_VAL(elt);			nextelt = DLGetSucc(elt);			if (ct->refcount > 0 ||				(ct->c_list && ct->c_list->refcount > 0))			{				ct->dead = true;				/* list, if any, was marked dead above */				Assert(ct->c_list == NULL || ct->c_list->dead);			}			else				CatCacheRemoveCTup(cache, ct);#ifdef CATCACHE_STATS			cache->cc_invals++;#endif		}	}}/* *		ResetCatalogCaches * * Reset all caches when a shared cache inval event forces it */voidResetCatalogCaches(void){	CatCache   *cache;	CACHE1_elog(DEBUG2, "ResetCatalogCaches called");	for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)		ResetCatalogCache(cache);	CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");}/* *		CatalogCacheFlushRelation * *	This is called by RelationFlushRelation() to clear out cached information *	about a relation being dropped.  (This could be a DROP TABLE command, *	or a temp table being dropped at end of transaction, or a table created *	during the current transaction that is being dropped because of abort.) *	Remove all cache entries relevant to the specified relation OID. * *	A special case occurs when relId is itself one of the cacheable system *	tables --- although those'll never be dropped, they can get flushed from *	the relcache (VACUUM causes this, for example).  In that case we need *	to flush all cache entries that came from that table.  (At one point we *	also tried to force re-execution of CatalogCacheInitializeCache for *	the cache(s) on that table.  This is a bad idea since it leads to all *	kinds of trouble if a cache flush occurs while loading cache entries. *	We now avoid the need to do it by copying cc_tupdesc out of the relcache, *	rather than relying on the relcache to keep a tupdesc for us.  Of course *	this assumes the tupdesc of a cachable system table will not change...) */voidCatalogCacheFlushRelation(Oid relId){	CatCache   *cache;	CACHE2_elog(DEBUG2, "CatalogCacheFlushRelation called for %u", relId);	for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)	{		int			i;		/* We can ignore uninitialized caches, since they must be empty */		if (cache->cc_tupdesc == NULL)			continue;		/* Does this cache store tuples of the target relation itself? */		if (cache->cc_tupdesc->attrs[0]->attrelid == relId)		{			/* Yes, so flush all its contents */			ResetCatalogCache(cache);			continue;		}		/* Does this cache store tuples associated with relations at all? */		if (cache->cc_reloidattr == 0)			continue;			/* nope, leave it alone */		/* Yes, scan the tuples and remove those related to relId */		for (i = 0; i < cache->cc_nbuckets; i++)		{			Dlelem	   *elt,					   *nextelt;			for (elt = DLGetHead(&cache->cc_bucket[i]); elt; elt = nextelt)			{				CatCTup    *ct = (CatCTup *) DLE_VAL(elt);				Oid			tupRelid;				nextelt = DLGetSucc(elt);				/*				 * Negative entries are never considered related to a rel,				 * even if the rel is part of their lookup key.				 */				if (ct->negative)					continue;				if (cache->cc_reloidattr == ObjectIdAttributeNumber)					tupRelid = HeapTupleGetOid(&ct->tuple);				else				{					bool		isNull;					tupRelid =						DatumGetObjectId(fastgetattr(&ct->tuple,													 cache->cc_reloidattr,													 cache->cc_tupdesc,													 &isNull));					Assert(!isNull);				}				if (tupRelid == relId)				{					if (ct->refcount > 0 ||						(ct->c_list && ct->c_list->refcount > 0))					{						ct->dead = true;						/* parent list must be considered dead too */						if (ct->c_list)							ct->c_list->dead = true;					}					else						CatCacheRemoveCTup(cache, ct);#ifdef CATCACHE_STATS					cache->cc_invals++;#endif				}			}		}	}	CACHE1_elog(DEBUG2, "end of CatalogCacheFlushRelation call");}/* *		InitCatCache * *	This allocates and initializes a cache for a system catalog relation. *	Actually, the cache is only partially initialized to avoid opening the *	relation.  The relation will be opened and the rest of the cache *	structure initialized on the first access. */#ifdef CACHEDEBUG#define InitCatCache_DEBUG2 \do { \	elog(DEBUG2, "InitCatCache: rel=%u ind=%u id=%d nkeys=%d size=%d", \		 cp->cc_reloid, cp->cc_indexoid, cp->id, \		 cp->cc_nkeys, cp->cc_nbuckets); \} while(0)#else#define InitCatCache_DEBUG2#endifCatCache *InitCatCache(int id,			 Oid reloid,			 Oid indexoid,			 int reloidattr,			 int nkeys,			 const int *key,			 int nbuckets){	CatCache   *cp;	MemoryContext oldcxt;	int			i;	/*	 * nbuckets is the number of hash buckets to use in this catcache.	 * Currently we just use a hard-wired estimate of an appropriate size for	 * each cache; maybe later make them dynamically resizable?	 *	 * nbuckets must be a power of two.  We check this via Assert rather than	 * a full runtime check because the values will be coming from constant	 * tables.	 *	 * If you're confused by the power-of-two check, see comments in	 * bitmapset.c for an explanation.	 */	Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);	/*	 * first switch to the cache context so our allocations do not vanish at	 * the end of a transaction	 */	if (!CacheMemoryContext)		CreateCacheMemoryContext();	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);	/*	 * if first time through, initialize the cache group header	 */	if (CacheHdr == NULL)	{		CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));		CacheHdr->ch_caches = NULL;		CacheHdr->ch_ntup = 0;#ifdef CATCACHE_STATS		/* set up to dump stats at backend exit */		on_proc_exit(CatCachePrintStats, 0);#endif	}	/*	 * allocate a new cache structure	 *	 * Note: we assume zeroing initializes the Dllist headers correctly	 */	cp = (CatCache *) palloc0(sizeof(CatCache) + nbuckets * sizeof(Dllist));	/*	 * initialize the cache's relation information for the relation	 * corresponding to this cache, and initialize some of the new cache's	 * other internal fields.  But don't open the relation yet.	 */	cp->id = id;	cp->cc_relname = "(not known yet)";	cp->cc_reloid = reloid;	cp->cc_indexoid = indexoid;	cp->cc_relisshared = false; /* temporary */	cp->cc_tupdesc = (TupleDesc) NULL;	cp->cc_reloidattr = reloidattr;	cp->cc_ntup = 0;	cp->cc_nbuckets = nbuckets;	cp->cc_nkeys = nkeys;	for (i = 0; i < nkeys; ++i)		cp->cc_key[i] = key[i];	/*	 * new cache is initialized as far as we can go for now. print some	 * debugging information, if appropriate.	 */	InitCatCache_DEBUG2;	/*	 * add completed cache to top of group header's list	 */	cp->cc_next = CacheHdr->ch_caches;	CacheHdr->ch_caches = cp;	/*	 * back to the old context before we return...	 */	MemoryContextSwitchTo(oldcxt);	return cp;}/* *		CatalogCacheInitializeCache * * This function does final initialization of a catcache: obtain the tuple * descriptor and set up the hash and equality function links.	We assume * that the relcache entry can be opened at this point! */#ifdef CACHEDEBUG#define CatalogCacheInitializeCache_DEBUG1 \	elog(DEBUG2, "CatalogCacheInitializeCache: cache @%p rel=%u", cache, \		 cache->cc_reloid)#define CatalogCacheInitializeCache_DEBUG2 \do { \		if (cache->cc_key[i] > 0) { \			elog(DEBUG2, "CatalogCacheInitializeCache: load %d/%d w/%d, %u", \				i+1, cache->cc_nkeys, cache->cc_key[i], \				 tupdesc->attrs[cache->cc_key[i] - 1]->atttypid); \		} else { \			elog(DEBUG2, "CatalogCacheInitializeCache: load %d/%d w/%d", \				i+1, cache->cc_nkeys, cache->cc_key[i]); \		} \} while(0)#else#define CatalogCacheInitializeCache_DEBUG1#define CatalogCacheInitializeCache_DEBUG2#endifstatic voidCatalogCacheInitializeCache(CatCache *cache){	Relation	relation;	MemoryContext oldcxt;	TupleDesc	tupdesc;	int			i;

⌨️ 快捷键说明

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