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