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

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