#include "access/htup.h"
#include "storage/relfilenode.h"
#include "utils/relcache.h"
Go to the source code of this file.
typedef void(* RelcacheCallbackFunction)(Datum arg, Oid relid) |
typedef void(* SyscacheCallbackFunction)(Datum arg, int cacheid, uint32 hashvalue) |
void AcceptInvalidationMessages | ( | void | ) |
Definition at line 588 of file inval.c.
References InvalidateSystemCaches(), LocalExecuteInvalidationMessage(), and ReceiveSharedInvalidMessages().
Referenced by AtStart_Cache(), ConditionalLockRelation(), ConditionalLockRelationOid(), LockDatabaseObject(), LockRelation(), LockRelationOid(), LockSharedObject(), ProcessCatchupEvent(), RangeVarGetRelidExtended(), relation_openrv(), relation_openrv_extended(), RemoveRelations(), and write_relcache_init_file().
{ ReceiveSharedInvalidMessages(LocalExecuteInvalidationMessage, InvalidateSystemCaches); /* * Test code to force cache flushes anytime a flush could happen. * * If used with CLOBBER_FREED_MEMORY, CLOBBER_CACHE_ALWAYS provides a * fairly thorough test that the system contains no cache-flush hazards. * However, it also makes the system unbelievably slow --- the regression * tests take about 100 times longer than normal. * * If you're a glutton for punishment, try CLOBBER_CACHE_RECURSIVELY. This * slows things by at least a factor of 10000, so I wouldn't suggest * trying to run the entire regression tests that way. It's useful to try * a few simple tests, to make sure that cache reload isn't subject to * internal cache-flush hazards, but after you've done a few thousand * recursive reloads it's unlikely you'll learn more. */ #if defined(CLOBBER_CACHE_ALWAYS) { static bool in_recursion = false; if (!in_recursion) { in_recursion = true; InvalidateSystemCaches(); in_recursion = false; } } #elif defined(CLOBBER_CACHE_RECURSIVELY) InvalidateSystemCaches(); #endif }
void AtEOSubXact_Inval | ( | bool | isCommit | ) |
Definition at line 890 of file inval.c.
References AppendInvalidationMessages(), Assert, CommandEndInvalidationMessages(), GetCurrentTransactionNestLevel(), LocalExecuteInvalidationMessage(), TransInvalidationInfo::my_level, NULL, TransInvalidationInfo::parent, pfree(), TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessages(), and TransInvalidationInfo::RelcacheInitFileInval.
Referenced by AbortSubTransaction(), and CommitSubTransaction().
{ int my_level = GetCurrentTransactionNestLevel(); TransInvalidationInfo *myInfo = transInvalInfo; if (isCommit) { /* Must be at non-top of stack */ Assert(myInfo != NULL && myInfo->parent != NULL); Assert(myInfo->my_level == my_level); /* If CurrentCmdInvalidMsgs still has anything, fix it */ CommandEndInvalidationMessages(); /* Pass up my inval messages to parent */ AppendInvalidationMessages(&myInfo->parent->PriorCmdInvalidMsgs, &myInfo->PriorCmdInvalidMsgs); /* Pending relcache inval becomes parent's problem too */ if (myInfo->RelcacheInitFileInval) myInfo->parent->RelcacheInitFileInval = true; /* Pop the transaction state stack */ transInvalInfo = myInfo->parent; /* Need not free anything else explicitly */ pfree(myInfo); } else if (myInfo != NULL && myInfo->my_level == my_level) { /* Must be at non-top of stack */ Assert(myInfo->parent != NULL); ProcessInvalidationMessages(&myInfo->PriorCmdInvalidMsgs, LocalExecuteInvalidationMessage); /* Pop the transaction state stack */ transInvalInfo = myInfo->parent; /* Need not free anything else explicitly */ pfree(myInfo); } }
void AtEOXact_Inval | ( | bool | isCommit | ) |
Definition at line 834 of file inval.c.
References AppendInvalidationMessages(), Assert, TransInvalidationInfo::CurrentCmdInvalidMsgs, LocalExecuteInvalidationMessage(), NULL, TransInvalidationInfo::parent, TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessages(), ProcessInvalidationMessagesMulti(), RelationCacheInitFilePostInvalidate(), RelationCacheInitFilePreInvalidate(), TransInvalidationInfo::RelcacheInitFileInval, and SendSharedInvalidMessages().
Referenced by AbortTransaction(), CommitTransaction(), and PostPrepare_Inval().
{ if (isCommit) { /* Must be at top of stack */ Assert(transInvalInfo != NULL && transInvalInfo->parent == NULL); /* * Relcache init file invalidation requires processing both before and * after we send the SI messages. However, we need not do anything * unless we committed. */ if (transInvalInfo->RelcacheInitFileInval) RelationCacheInitFilePreInvalidate(); AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, &transInvalInfo->CurrentCmdInvalidMsgs); ProcessInvalidationMessagesMulti(&transInvalInfo->PriorCmdInvalidMsgs, SendSharedInvalidMessages); if (transInvalInfo->RelcacheInitFileInval) RelationCacheInitFilePostInvalidate(); } else if (transInvalInfo != NULL) { /* Must be at top of stack */ Assert(transInvalInfo->parent == NULL); ProcessInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, LocalExecuteInvalidationMessage); } /* Need not free anything explicitly */ transInvalInfo = NULL; }
void AtPrepare_Inval | ( | void | ) |
void AtStart_Inval | ( | void | ) |
Definition at line 629 of file inval.c.
References Assert, GetCurrentTransactionNestLevel(), MemoryContextAllocZero(), TransInvalidationInfo::my_level, NULL, numSharedInvalidMessagesArray, and TopTransactionContext.
Referenced by StartTransaction().
void AtSubStart_Inval | ( | void | ) |
Definition at line 663 of file inval.c.
References Assert, GetCurrentTransactionNestLevel(), MemoryContextAllocZero(), TransInvalidationInfo::my_level, NULL, TransInvalidationInfo::parent, and TopTransactionContext.
Referenced by StartSubTransaction().
{ TransInvalidationInfo *myInfo; Assert(transInvalInfo != NULL); myInfo = (TransInvalidationInfo *) MemoryContextAllocZero(TopTransactionContext, sizeof(TransInvalidationInfo)); myInfo->parent = transInvalInfo; myInfo->my_level = GetCurrentTransactionNestLevel(); transInvalInfo = myInfo; }
void CacheInvalidateCatalog | ( | Oid | catalogId | ) |
Definition at line 1082 of file inval.c.
References IsSharedRelation(), MyDatabaseId, and RegisterCatalogInvalidation().
Referenced by finish_heap_swap().
{ Oid databaseId; if (IsSharedRelation(catalogId)) databaseId = InvalidOid; else databaseId = MyDatabaseId; RegisterCatalogInvalidation(databaseId, catalogId); }
Definition at line 979 of file inval.c.
References AttributeRelationId, GETSTRUCT, HeapTupleGetOid, IndexRelationId, IsBootstrapProcessingMode, IsSystemRelation(), IsToastRelation(), MyDatabaseId, PrepareToInvalidateCacheTuple(), RegisterCatcacheInvalidation(), RegisterRelcacheInvalidation(), RelationGetRelid, and RelationRelationId.
Referenced by heap_delete(), heap_inplace_update(), heap_insert(), heap_multi_insert(), and heap_update().
{ Oid tupleRelId; Oid databaseId; Oid relationId; /* Do nothing during bootstrap */ if (IsBootstrapProcessingMode()) return; /* * We only need to worry about invalidation for tuples that are in system * relations; user-relation tuples are never in catcaches and can't affect * the relcache either. */ if (!IsSystemRelation(relation)) return; /* * TOAST tuples can likewise be ignored here. Note that TOAST tables are * considered system relations so they are not filtered by the above test. */ if (IsToastRelation(relation)) return; /* * First let the catcache do its thing */ PrepareToInvalidateCacheTuple(relation, tuple, newtuple, RegisterCatcacheInvalidation); /* * Now, is this tuple one of the primary definers of a relcache entry? * * Note we ignore newtuple here; we assume an update cannot move a tuple * from being part of one relcache entry to being part of another. */ tupleRelId = RelationGetRelid(relation); if (tupleRelId == RelationRelationId) { Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple); relationId = HeapTupleGetOid(tuple); if (classtup->relisshared) databaseId = InvalidOid; else databaseId = MyDatabaseId; } else if (tupleRelId == AttributeRelationId) { Form_pg_attribute atttup = (Form_pg_attribute) GETSTRUCT(tuple); relationId = atttup->attrelid; /* * KLUGE ALERT: we always send the relcache event with MyDatabaseId, * even if the rel in question is shared (which we can't easily tell). * This essentially means that only backends in this same database * will react to the relcache flush request. This is in fact * appropriate, since only those backends could see our pg_attribute * change anyway. It looks a bit ugly though. (In practice, shared * relations can't have schema changes after bootstrap, so we should * never come here for a shared rel anyway.) */ databaseId = MyDatabaseId; } else if (tupleRelId == IndexRelationId) { Form_pg_index indextup = (Form_pg_index) GETSTRUCT(tuple); /* * When a pg_index row is updated, we should send out a relcache inval * for the index relation. As above, we don't know the shared status * of the index, but in practice it doesn't matter since indexes of * shared catalogs can't have such updates. */ relationId = indextup->indexrelid; databaseId = MyDatabaseId; } else return; /* * Yes. We need to register a relcache invalidation event. */ RegisterRelcacheInvalidation(databaseId, relationId); }
void CacheInvalidateRelcache | ( | Relation | relation | ) |
Definition at line 1104 of file inval.c.
References MyDatabaseId, RelationData::rd_rel, RegisterRelcacheInvalidation(), and RelationGetRelid.
Referenced by _bt_getroot(), _bt_insertonpg(), _bt_newroot(), _bt_pagedel(), ATExecValidateConstraint(), EnableDisableRule(), EnableDisableTrigger(), index_drop(), reindex_index(), RemoveRewriteRuleById(), RemoveTriggerById(), RenameRewriteRule(), renametrig(), and SetRelationNumChecks().
{ Oid databaseId; Oid relationId; relationId = RelationGetRelid(relation); if (relation->rd_rel->relisshared) databaseId = InvalidOid; else databaseId = MyDatabaseId; RegisterRelcacheInvalidation(databaseId, relationId); }
void CacheInvalidateRelcacheByRelid | ( | Oid | relid | ) |
Definition at line 1144 of file inval.c.
References CacheInvalidateRelcacheByTuple(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RELOID, and SearchSysCache1.
Referenced by DefineIndex().
{ HeapTuple tup; tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for relation %u", relid); CacheInvalidateRelcacheByTuple(tup); ReleaseSysCache(tup); }
void CacheInvalidateRelcacheByTuple | ( | HeapTuple | classTuple | ) |
Definition at line 1123 of file inval.c.
References GETSTRUCT, HeapTupleGetOid, MyDatabaseId, and RegisterRelcacheInvalidation().
Referenced by CacheInvalidateRelcacheByRelid(), index_update_stats(), SetRelationHasSubclass(), SetRelationRuleStatus(), and swap_relation_files().
{ Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple); Oid databaseId; Oid relationId; relationId = HeapTupleGetOid(classTuple); if (classtup->relisshared) databaseId = InvalidOid; else databaseId = MyDatabaseId; RegisterRelcacheInvalidation(databaseId, relationId); }
void CacheInvalidateRelmap | ( | Oid | databaseId | ) |
Definition at line 1209 of file inval.c.
References SharedInvalRelmapMsg::dbId, SharedInvalRelmapMsg::id, SharedInvalidationMessage::rm, and SendSharedInvalidMessages().
Referenced by write_relmap_file().
{ SharedInvalidationMessage msg; msg.rm.id = SHAREDINVALRELMAP_ID; msg.rm.dbId = databaseId; SendSharedInvalidMessages(&msg, 1); }
void CacheInvalidateSmgr | ( | RelFileNodeBackend | rnode | ) |
Definition at line 1182 of file inval.c.
References RelFileNodeBackend::backend, SharedInvalSmgrMsg::backend_hi, SharedInvalSmgrMsg::backend_lo, SharedInvalSmgrMsg::id, RelFileNodeBackend::node, SharedInvalSmgrMsg::rnode, SendSharedInvalidMessages(), and SharedInvalidationMessage::sm.
Referenced by smgrdounlink(), smgrdounlinkall(), smgrdounlinkfork(), smgrtruncate(), and vm_extend().
{ SharedInvalidationMessage msg; msg.sm.id = SHAREDINVALSMGR_ID; msg.sm.backend_hi = rnode.backend >> 16; msg.sm.backend_lo = rnode.backend & 0xffff; msg.sm.rnode = rnode.node; SendSharedInvalidMessages(&msg, 1); }
void CacheRegisterRelcacheCallback | ( | RelcacheCallbackFunction | func, | |
Datum | arg | |||
) |
Definition at line 1257 of file inval.c.
References RELCACHECALLBACK::arg, elog, FATAL, RELCACHECALLBACK::function, MAX_RELCACHE_CALLBACKS, relcache_callback_count, and relcache_callback_list.
Referenced by InitPlanCache(), and lookup_type_cache().
{ if (relcache_callback_count >= MAX_RELCACHE_CALLBACKS) elog(FATAL, "out of relcache_callback_list slots"); relcache_callback_list[relcache_callback_count].function = func; relcache_callback_list[relcache_callback_count].arg = arg; ++relcache_callback_count; }
void CacheRegisterSyscacheCallback | ( | int | cacheid, | |
SyscacheCallbackFunction | func, | |||
Datum | arg | |||
) |
Definition at line 1233 of file inval.c.
References SYSCACHECALLBACK::arg, elog, FATAL, SYSCACHECALLBACK::function, SYSCACHECALLBACK::id, MAX_SYSCACHE_CALLBACKS, syscache_callback_count, and syscache_callback_list.
Referenced by BuildEventTriggerCache(), find_oper_cache_entry(), get_btree_test_op(), init_ts_config_cache(), initialize_acl(), InitializeAttoptCache(), InitializeSearchPath(), InitializeTableSpaceCache(), InitPlanCache(), lookup_ts_dictionary_cache(), lookup_ts_parser_cache(), ri_InitHashTables(), and superuser_arg().
{ if (syscache_callback_count >= MAX_SYSCACHE_CALLBACKS) elog(FATAL, "out of syscache_callback_list slots"); syscache_callback_list[syscache_callback_count].id = cacheid; syscache_callback_list[syscache_callback_count].function = func; syscache_callback_list[syscache_callback_count].arg = arg; ++syscache_callback_count; }
void CallSyscacheCallbacks | ( | int | cacheid, | |
uint32 | hashvalue | |||
) |
Definition at line 1276 of file inval.c.
References SYSCACHECALLBACK::arg, SYSCACHECALLBACK::function, i, SYSCACHECALLBACK::id, syscache_callback_count, and syscache_callback_list.
Referenced by CatalogCacheFlushCatalog(), and LocalExecuteInvalidationMessage().
{ int i; for (i = 0; i < syscache_callback_count; i++) { struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i; if (ccitem->id == cacheid) (*ccitem->function) (ccitem->arg, cacheid, hashvalue); } }
void CommandEndInvalidationMessages | ( | void | ) |
Definition at line 950 of file inval.c.
References AppendInvalidationMessages(), TransInvalidationInfo::CurrentCmdInvalidMsgs, LocalExecuteInvalidationMessage(), NULL, TransInvalidationInfo::PriorCmdInvalidMsgs, and ProcessInvalidationMessages().
Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().
{ /* * You might think this shouldn't be called outside any transaction, but * bootstrap does it, and also ABORT issued when not in a transaction. So * just quietly return if no state to work on. */ if (transInvalInfo == NULL) return; ProcessInvalidationMessages(&transInvalInfo->CurrentCmdInvalidMsgs, LocalExecuteInvalidationMessage); AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, &transInvalInfo->CurrentCmdInvalidMsgs); }
void inval_twophase_postcommit | ( | TransactionId | xid, | |
uint16 | info, | |||
void * | recdata, | |||
uint32 | len | |||
) |
void PostPrepare_Inval | ( | void | ) |
Definition at line 653 of file inval.c.
References AtEOXact_Inval().
Referenced by PrepareTransaction().
{ AtEOXact_Inval(false); }