📄 syscache.c
字号:
static struct catcache *SysCache[lengthof(cacheinfo)];static int32 SysCacheSize = lengthof(cacheinfo);/* * zerocaches * * Make sure the SysCache structure is zero'd. */voidzerocaches(){ MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));}/* * Note: * This function was written because the initialized catalog caches * are used to determine which caches may contain tuples which need * to be invalidated in other backends. */voidInitCatalogCache(){ int cacheId; /* XXX type */ if (!AMI_OVERRIDE) { for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) { Assert(!PointerIsValid((Pointer) SysCache[cacheId])); SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name, cacheinfo[cacheId].indname, cacheId, cacheinfo[cacheId].nkeys, cacheinfo[cacheId].key, cacheinfo[cacheId].iScanFunc); if (!PointerIsValid((char *) SysCache[cacheId])) { elog(ERROR, "InitCatalogCache: Can't init cache %s(%d)", cacheinfo[cacheId].name, cacheId); } } }}/* * SearchSysCacheTupleCopy * * This is like SearchSysCacheTuple, except it returns a copy of the tuple * that the user is required to pfree(). */HeapTupleSearchSysCacheTupleCopy(int cacheId, /* cache selection code */ Datum key1, Datum key2, Datum key3, Datum key4){ HeapTuple cachetup; cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); if (PointerIsValid(cachetup)) return heap_copytuple(cachetup); else return cachetup; /* NULL */}/* * SearchSysCacheTuple * * A layer on top of SearchSysCache that does the initialization and * key-setting for you. * * Returns the cache copy of the tuple if one is found, NULL if not. * The tuple is the 'cache' copy. * * XXX The tuple that is returned is NOT supposed to be pfree'd! */HeapTupleSearchSysCacheTuple(int cacheId,/* cache selection code */ Datum key1, Datum key2, Datum key3, Datum key4){ HeapTuple tp; if (cacheId < 0 || cacheId >= SysCacheSize) { elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId); return (HeapTuple) NULL; } Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId])); if (!PointerIsValid(SysCache[cacheId])) { SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name, cacheinfo[cacheId].indname, cacheId, cacheinfo[cacheId].nkeys, cacheinfo[cacheId].key, cacheinfo[cacheId].iScanFunc); if (!PointerIsValid(SysCache[cacheId])) elog(ERROR, "InitCatalogCache: Can't init cache %s(%d)", cacheinfo[cacheId].name, cacheId); } tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4); if (!HeapTupleIsValid(tp)) {#ifdef CACHEDEBUG elog(DEBUG, "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", cacheinfo[cacheId].name, cacheId, key1, key2, key3, key4);#endif return (HeapTuple) NULL; } return tp;}/* * SearchSysCacheStruct * Fills 's' with the information retrieved by calling SearchSysCache() * with arguments key1...key4. Retrieves only the portion of the tuple * which is not variable-length. * * NOTE: we are assuming that non-variable-length fields in the system * catalogs will always be defined! * * Returns 1L if a tuple was found, 0L if not. */int32SearchSysCacheStruct(int cacheId, /* cache selection code */ char *returnStruct, /* (preallocated!) */ Datum key1, Datum key2, Datum key3, Datum key4){ HeapTuple tp; if (!PointerIsValid(returnStruct)) { elog(ERROR, "SearchSysCacheStruct: No receiving struct"); return 0; } tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); if (!HeapTupleIsValid(tp)) return 0; memcpy(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size); return 1;}/* * SearchSysCacheGetAttribute * Returns the attribute corresponding to 'attributeNumber' for * a given cached tuple. This routine usually needs to be used for * attributes that might be NULL or might be at a variable offset * in the tuple. * * XXX This re-opens the relation, so this is slower than just pulling * fixed-location fields out of the struct returned by SearchSysCacheTuple. * * [callers all assume this returns a (struct varlena *). -ay 10/94] */void *SearchSysCacheGetAttribute(int cacheId, AttrNumber attributeNumber, Datum key1, Datum key2, Datum key3, Datum key4){ HeapTuple tp; char *cacheName; Relation relation; int32 attributeLength, attributeByValue; bool isNull; Datum attributeValue; void *returnValue; tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); cacheName = cacheinfo[cacheId].name; if (!HeapTupleIsValid(tp)) {#ifdef CACHEDEBUG elog(DEBUG, "SearchSysCacheGetAttribute: Lookup in %s(%d) failed", cacheName, cacheId);#endif /* defined(CACHEDEBUG) */ return NULL; } relation = heap_openr(cacheName); if (attributeNumber < 0 && attributeNumber > FirstLowInvalidHeapAttributeNumber) { attributeLength = heap_sysattrlen(attributeNumber); attributeByValue = heap_sysattrbyval(attributeNumber); } else if (attributeNumber > 0 && attributeNumber <= relation->rd_rel->relnatts) { attributeLength = relation->rd_att->attrs[attributeNumber - 1]->attlen; attributeByValue = relation->rd_att->attrs[attributeNumber - 1]->attbyval; } else { elog(ERROR, "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", attributeNumber, cacheName, cacheId); return NULL; } attributeValue = heap_getattr(tp, attributeNumber, RelationGetDescr(relation), &isNull); if (isNull) { /* * Used to be an elog(DEBUG, ...) here and a claim that it should * be a FATAL error, I don't think either is warranted -mer 6/9/92 */ return NULL; } if (attributeByValue) returnValue = (void *) attributeValue; else { char *tmp; int size = (attributeLength < 0) ? VARSIZE((struct varlena *) attributeValue) /* variable length */ : attributeLength; /* fixed length */ tmp = (char *) palloc(size); memcpy(tmp, (void *) attributeValue, size); returnValue = (void *) tmp; } heap_close(relation); return returnValue;}/* * TypeDefaultRetrieve * * Given a type OID, return the typdefault field associated with that * type. The result is a Datum, and points to palloc'd storage for * non-pass-by-value types. * * [identical to get_typdefault, expecting a (struct varlena *) as ret val. * some day, either of the functions should be removed -ay 10/94] */void *TypeDefaultRetrieve(Oid typId){ struct varlena *typDefault; int32 dataSize; HeapTuple typeTuple; Form_pg_type type; int32 typByVal, typLen; void *returnValue; /* * First, see if there is a non-null typdefault field (usually there isn't) */ typDefault = (struct varlena *) SearchSysCacheGetAttribute(TYPOID, Anum_pg_type_typdefault, ObjectIdGetDatum(typId), 0, 0, 0); if (typDefault == NULL) {#ifdef CACHEDEBUG elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)", cacheinfo[TYPOID].name, TYPOID);#endif /* defined(CACHEDEBUG) */ return NULL; } dataSize = VARSIZE(typDefault) - VARHDRSZ; /* * Need the type's length and byVal fields. * * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute * just did --- but at present this path isn't taken often enough to * make it worth fixing. */ typeTuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(typId), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) { /* should never get here, really... */#ifdef CACHEDEBUG elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed", cacheinfo[TYPOID].name, TYPOID);#endif /* defined(CACHEDEBUG) */ return NULL; } type = (Form_pg_type) GETSTRUCT(typeTuple); typLen = type->typlen; typByVal = type->typbyval; if (typByVal) { int8 i8; int16 i16; int32 i32 = 0; if (dataSize == typLen) { switch (typLen) { case sizeof(int8): memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8)); i32 = i8; break; case sizeof(int16): memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16)); i32 = i16; break; case sizeof(int32): memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32)); break; } returnValue = (void *) i32; } else returnValue = NULL; } else { if ((typLen < 0 && dataSize < 0) || dataSize != typLen) returnValue = NULL; else { returnValue = (void *) palloc(VARSIZE(typDefault)); memcpy((char *) returnValue, (char *) typDefault, (int) VARSIZE(typDefault)); } } return returnValue;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -