#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);
}
1.7.1