SearchCatCache

SearchCatCache
简介:
这个函数根据给定的查找键值查找一个系统缓存来查找一个tuple,(如果是第一次进入cache,打开对应的表建立一个缓存)如果在cache中找到该tuple就返回一个指向cache中tuple的指针。 如果没有找到该tuple就会在实际表中查找,如果找到就会构建一个positive的tuple放到cache中,返回该tuple,如果没有找到,那么会构建一个假的tuple,这个假的tuple的标记为negative,然后把假的tuple放到cache中,返回一个NULL。
查找键值应该作一个Datum类型传入,可以根据提供的宏进行转换如(ObjectIdGetDatum)没有使用的传递0。
流程:

  1. 首先确认该函数必须在一个事务中
  2. 如果cache->cc_tupdesc == NULL的话,表示第一次进入,进行初始化。
  3. 根据传入的参数进行HASH计算,然后进行HASH查找,这里采用的是溢出桶处理的。如果找到,那么将该tuple放在链表的头部,并且返回该tuple。
  4. 如果没有找到,那么我们尝试从表中直接查找,如果在表中找到,把它放到cache中,如果没有找到,那么就会构建一个假的tuple,该tuple标记为negtive,同样也放入cache。
HeapTuple
SearchCatCache(CatCache *cache,
			   Datum v1,
			   Datum v2,
			   Datum v3,
			   Datum v4)
{
	ScanKeyData cur_skey[CATCACHE_MAXKEYS];
	uint32		hashValue;
	Index		hashIndex;
	dlist_iter	iter;
	dlist_head *bucket;
	CatCTup    *ct;
	Relation	relation;
	SysScanDesc scandesc;
	HeapTuple	ntp;
	Oid		subtypeoid = InvalidOid;

	/* 首先确保查找在一个事务中*/
	Assert(IsTransactionState());
	/*如果是第一次查找,那么会进行cache的初始化操作*/
	if (cache->cc_tupdesc == NULL)
		CatalogCacheInitializeCache(cache);

#ifdef CATCACHE_STATS
	cache->cc_searches++;
#endif

	/* 初始化查找关键字信息 */
	memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
	cur_skey[0].sk_argument = v1;
	cur_skey[1].sk_argument = v2;
	cur_skey[2].sk_argument = v3;
	cur_skey[3].sk_argument = v4;

	/* 进行HASH查找 */
	hashValue = CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
	hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
	....../*查找过程省略,会在其他文章中介绍*/
	/* 如果找到一个匹配的,那么把它放到链表最前面,加速以后查抄 */
		dlist_move_head(bucket, &ct->cache_elem);
	/* 如果是一个积极入口,增加它的引用计数,并且返回它 */
		if (!ct->negative)
		{
			ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner);
			ct->refcount++;
			ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple);
			return &ct->tuple;
		}
		/* 否则的话,它是一个我们自己构建的虚拟的tuple,返回NULL */
		else
		{
				return NULL;
		}
	}

	/* 如果tuple没有在cache中找到,我们就会试图从表中进行查找,如果找到就把它加入到cache中,如果没有找到,我们会构建一个假的tuple,也把它放到cache中,那是标记为negtive,见上面*/
	relation = heap_open(cache->cc_reloid, AccessShareLock);
	scandesc = systable_beginscan(relation,
								  cache->cc_indexoid,
								  IndexScanOK(cache, cur_skey),
								  NULL,
								  cache->cc_nkeys,
								  cur_skey);

	ct = NULL;

	while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
	{
		ct = CatalogCacheCreateEntry(cache, ntp,
									 hashValue, hashIndex,
									 false);
		/* immediately set the refcount to 1 */
		ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner);
		ct->refcount++;
		ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple);
		break;					/* assume only one match */
	}

	systable_endscan(scandesc);

	heap_close(relation, AccessShareLock);
	/* 如果没有找到就构建一个假的,并标记为negtive */
	if (ct == NULL)
	{
		ntp = build_dummy_tuple(cache, cache->cc_nkeys, cur_skey);
		ct = CatalogCacheCreateEntry(cache, ntp,
									 hashValue, hashIndex,
									 true); //最后的true表示是否为negative
		heap_freetuple(ntp);

		return NULL;
	}
	return &ct->tuple;
}

CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, uint32 hashValue, Index hashIndex, bool negative)CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, uint32 hashValue, Index hashIndex, bool negative)
最后一个参数标识是否为negative

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章