SearchCatCache
簡介:
這個函數根據給定的查找鍵值查找一個系統緩存來查找一個tuple,(如果是第一次進入cache,打開對應的表建立一個緩存)如果在cache中找到該tuple就返回一個指向cache中tuple的指針。 如果沒有找到該tuple就會在實際表中查找,如果找到就會構建一個positive的tuple放到cache中,返回該tuple,如果沒有找到,那麼會構建一個假的tuple,這個假的tuple的標記爲negative,然後把假的tuple放到cache中,返回一個NULL。
查找鍵值應該作一個Datum類型傳入,可以根據提供的宏進行轉換如(ObjectIdGetDatum)沒有使用的傳遞0。
流程:
- 首先確認該函數必須在一個事務中
- 如果cache->cc_tupdesc == NULL的話,表示第一次進入,進行初始化。
- 根據傳入的參數進行HASH計算,然後進行HASH查找,這裏採用的是溢出桶處理的。如果找到,那麼將該tuple放在鏈表的頭部,並且返回該tuple。
- 如果沒有找到,那麼我們嘗試從表中直接查找,如果在表中找到,把它放到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