/* * LocalExecuteInvalidationMessage * * Process a single invalidation message (which could be of any type). * Only the local caches are flushed; this does not transmit the message * to other backends. */ static void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg) { if (msg->id >= 0) { if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid) { CatalogCacheIdInvalidate(msg->cc.id, msg->cc.hashValue); CallSyscacheCallbacks(msg->cc.id, msg->cc.hashValue); } } else if (msg->id == SHAREDINVALCATALOG_ID) { if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid) { CatalogCacheFlushCatalog(msg->cat.catId); /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */ } } else if (msg->id == SHAREDINVALRELCACHE_ID) { if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid) { int i; RelationCacheInvalidateEntry(msg->rc.relId); for (i = 0; i < relcache_callback_count; i++) { struct RELCACHECALLBACK *ccitem = relcache_callback_list + i; (*ccitem->function) (ccitem->arg, msg->rc.relId); } } } else if (msg->id == SHAREDINVALSMGR_ID) { /* * We could have smgr entries for relations of other databases, so no * short-circuit test is possible here. */ RelFileNodeBackend rnode; rnode.node = msg->sm.rnode; rnode.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo; smgrclosenode(rnode); } else if (msg->id == SHAREDINVALRELMAP_ID) { /* We only care about our own database and shared catalogs */ if (msg->rm.dbId == InvalidOid) RelationMapInvalidate(true); else if (msg->rm.dbId == MyDatabaseId) RelationMapInvalidate(false); } else elog(FATAL, "unrecognized SI message ID: %d", msg->id); }
/* * CatalogCacheFlushCatalog * * Flush all catcache entries that came from the specified system catalog. * This is needed after VACUUM FULL/CLUSTER on the catalog, since the * tuples very likely now have different TIDs than before. (At one point * we also tried to force re-execution of CatalogCacheInitializeCache for * the cache(s) on that catalog. This is a bad idea since it leads to all * kinds of trouble if a cache flush occurs while loading cache entries. * We now avoid the need to do it by copying cc_tupdesc out of the relcache, * rather than relying on the relcache to keep a tupdesc for us. Of course * this assumes the tupdesc of a cachable system table will not change...) */ void CatalogCacheFlushCatalog(Oid catId) { CatCache *cache; CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId); for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next) { /* We can ignore uninitialized caches, since they must be empty */ if (cache->cc_tupdesc == NULL) continue; /* Does this cache store tuples of the target catalog? */ if (cache->cc_tupdesc->attrs[0]->attrelid == catId) { /* Yes, so flush all its contents */ ResetCatalogCache(cache); /* Tell inval.c to call syscache callbacks for this cache */ CallSyscacheCallbacks(cache->id, NULL); } } CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call"); }
/* * CatalogCacheFlushCatalog * * Flush all catcache entries that came from the specified system catalog. * This is needed after VACUUM FULL/CLUSTER on the catalog, since the * tuples very likely now have different TIDs than before. (At one point * we also tried to force re-execution of CatalogCacheInitializeCache for * the cache(s) on that catalog. This is a bad idea since it leads to all * kinds of trouble if a cache flush occurs while loading cache entries. * We now avoid the need to do it by copying cc_tupdesc out of the relcache, * rather than relying on the relcache to keep a tupdesc for us. Of course * this assumes the tupdesc of a cachable system table will not change...) */ void CatalogCacheFlushCatalog(Oid catId) { CatCache *cache; CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId); for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next) { /* Does this cache store tuples of the target catalog? */ if (cache->cc_reloid == catId) { /* Yes, so flush all its contents */ ResetCatalogCache(cache); /* Tell inval.c to call syscache callbacks for this cache */ CallSyscacheCallbacks(cache->id, 0); } } CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call"); }