#include "postgres.h"#include "access/htup_details.h"#include "access/xact.h"#include "catalog/catalog.h"#include "miscadmin.h"#include "storage/sinval.h"#include "storage/smgr.h"#include "utils/catcache.h"#include "utils/inval.h"#include "utils/memutils.h"#include "utils/rel.h"#include "utils/relmapper.h"#include "utils/syscache.h"
Go to the source code of this file.
| #define FIRSTCHUNKSIZE 32 |
Referenced by AddInvalidationMessage().
| #define MAX_RELCACHE_CALLBACKS 5 |
Definition at line 180 of file inval.c.
Referenced by CacheRegisterRelcacheCallback().
| #define MAX_SYSCACHE_CALLBACKS 32 |
Definition at line 179 of file inval.c.
Referenced by CacheRegisterSyscacheCallback().
| #define ProcessMessageList | ( | listHdr, | ||
| codeFragment | ||||
| ) |
do { \ InvalidationChunk *_chunk; \ for (_chunk = (listHdr); _chunk != NULL; _chunk = _chunk->next) \ { \ int _cindex; \ for (_cindex = 0; _cindex < _chunk->nitems; _cindex++) \ { \ SharedInvalidationMessage *msg = &_chunk->msgs[_cindex]; \ codeFragment; \ } \ } \ } while (0)
Definition at line 281 of file inval.c.
Referenced by AddRelcacheInvalidationMessage(), and ProcessInvalidationMessages().
| #define ProcessMessageListMulti | ( | listHdr, | ||
| codeFragment | ||||
| ) |
do { \ InvalidationChunk *_chunk; \ for (_chunk = (listHdr); _chunk != NULL; _chunk = _chunk->next) \ { \ SharedInvalidationMessage *msgs = _chunk->msgs; \ int n = _chunk->nitems; \ codeFragment; \ } \ } while (0)
Definition at line 301 of file inval.c.
Referenced by ProcessInvalidationMessagesMulti().
| typedef struct InvalidationChunk InvalidationChunk |
| typedef struct InvalidationListHeader InvalidationListHeader |
| typedef struct TransInvalidationInfo TransInvalidationInfo |
| 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
}
| static void AddCatalogInvalidationMessage | ( | InvalidationListHeader * | hdr, | |
| Oid | dbId, | |||
| Oid | catId | |||
| ) | [static] |
Definition at line 341 of file inval.c.
References AddInvalidationMessage(), SharedInvalidationMessage::cat, SharedInvalCatalogMsg::catId, InvalidationListHeader::cclist, SharedInvalCatalogMsg::dbId, and SharedInvalCatalogMsg::id.
Referenced by RegisterCatalogInvalidation().
{
SharedInvalidationMessage msg;
msg.cat.id = SHAREDINVALCATALOG_ID;
msg.cat.dbId = dbId;
msg.cat.catId = catId;
AddInvalidationMessage(&hdr->cclist, &msg);
}
| static void AddCatcacheInvalidationMessage | ( | InvalidationListHeader * | hdr, | |
| int | id, | |||
| uint32 | hashValue, | |||
| Oid | dbId | |||
| ) | [static] |
Definition at line 325 of file inval.c.
References AddInvalidationMessage(), Assert, SharedInvalidationMessage::cc, InvalidationListHeader::cclist, SharedInvalCatcacheMsg::dbId, SharedInvalCatcacheMsg::hashValue, and SharedInvalCatcacheMsg::id.
Referenced by RegisterCatcacheInvalidation().
{
SharedInvalidationMessage msg;
Assert(id < CHAR_MAX);
msg.cc.id = (int8) id;
msg.cc.dbId = dbId;
msg.cc.hashValue = hashValue;
AddInvalidationMessage(&hdr->cclist, &msg);
}
| static void AddInvalidationMessage | ( | InvalidationChunk ** | listHdr, | |
| SharedInvalidationMessage * | msg | |||
| ) | [static] |
Definition at line 215 of file inval.c.
References CurTransactionContext, FIRSTCHUNKSIZE, InvalidationChunk::maxitems, MemoryContextAlloc(), InvalidationChunk::msgs, InvalidationChunk::next, InvalidationChunk::nitems, and NULL.
Referenced by AddCatalogInvalidationMessage(), AddCatcacheInvalidationMessage(), and AddRelcacheInvalidationMessage().
{
InvalidationChunk *chunk = *listHdr;
if (chunk == NULL)
{
/* First time through; create initial chunk */
#define FIRSTCHUNKSIZE 32
chunk = (InvalidationChunk *)
MemoryContextAlloc(CurTransactionContext,
sizeof(InvalidationChunk) +
(FIRSTCHUNKSIZE - 1) *sizeof(SharedInvalidationMessage));
chunk->nitems = 0;
chunk->maxitems = FIRSTCHUNKSIZE;
chunk->next = *listHdr;
*listHdr = chunk;
}
else if (chunk->nitems >= chunk->maxitems)
{
/* Need another chunk; double size of last chunk */
int chunksize = 2 * chunk->maxitems;
chunk = (InvalidationChunk *)
MemoryContextAlloc(CurTransactionContext,
sizeof(InvalidationChunk) +
(chunksize - 1) *sizeof(SharedInvalidationMessage));
chunk->nitems = 0;
chunk->maxitems = chunksize;
chunk->next = *listHdr;
*listHdr = chunk;
}
/* Okay, add message to current chunk */
chunk->msgs[chunk->nitems] = *msg;
chunk->nitems++;
}
| static void AddRelcacheInvalidationMessage | ( | InvalidationListHeader * | hdr, | |
| Oid | dbId, | |||
| Oid | relId | |||
| ) | [static] |
Definition at line 356 of file inval.c.
References AddInvalidationMessage(), SharedInvalRelcacheMsg::dbId, SharedInvalRelcacheMsg::id, ProcessMessageList, SharedInvalidationMessage::rc, InvalidationListHeader::rclist, SharedInvalRelcacheMsg::relId, and SHAREDINVALRELCACHE_ID.
Referenced by RegisterRelcacheInvalidation().
{
SharedInvalidationMessage msg;
/* Don't add a duplicate item */
/* We assume dbId need not be checked because it will never change */
ProcessMessageList(hdr->rclist,
if (msg->rc.id == SHAREDINVALRELCACHE_ID &&
msg->rc.relId == relId)
return);
/* OK, add the item */
msg.rc.id = SHAREDINVALRELCACHE_ID;
msg.rc.dbId = dbId;
msg.rc.relId = relId;
AddInvalidationMessage(&hdr->rclist, &msg);
}
| static void AppendInvalidationMessageList | ( | InvalidationChunk ** | destHdr, | |
| InvalidationChunk ** | srcHdr | |||
| ) | [static] |
Definition at line 257 of file inval.c.
References InvalidationChunk::next, and NULL.
Referenced by AppendInvalidationMessages().
| static void AppendInvalidationMessages | ( | InvalidationListHeader * | dest, | |
| InvalidationListHeader * | src | |||
| ) | [static] |
Definition at line 380 of file inval.c.
References AppendInvalidationMessageList(), InvalidationListHeader::cclist, and InvalidationListHeader::rclist.
Referenced by AtEOSubXact_Inval(), AtEOXact_Inval(), and CommandEndInvalidationMessages().
{
AppendInvalidationMessageList(&dest->cclist, &src->cclist);
AppendInvalidationMessageList(&dest->rclist, &src->rclist);
}
| 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 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);
}
| static void InvalidateSystemCaches | ( | void | ) | [static] |
Definition at line 551 of file inval.c.
References RELCACHECALLBACK::arg, SYSCACHECALLBACK::arg, RELCACHECALLBACK::function, SYSCACHECALLBACK::function, i, SYSCACHECALLBACK::id, InvalidOid, RelationCacheInvalidate(), relcache_callback_count, relcache_callback_list, ResetCatalogCaches(), syscache_callback_count, and syscache_callback_list.
Referenced by AcceptInvalidationMessages().
{
int i;
ResetCatalogCaches();
RelationCacheInvalidate(); /* gets smgr and relmap too */
for (i = 0; i < syscache_callback_count; i++)
{
struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
(*ccitem->function) (ccitem->arg, ccitem->id, 0);
}
for (i = 0; i < relcache_callback_count; i++)
{
struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
(*ccitem->function) (ccitem->arg, InvalidOid);
}
}
| static void LocalExecuteInvalidationMessage | ( | SharedInvalidationMessage * | msg | ) | [static] |
Definition at line 479 of file inval.c.
References RELCACHECALLBACK::arg, RelFileNodeBackend::backend, SharedInvalSmgrMsg::backend_hi, SharedInvalSmgrMsg::backend_lo, CallSyscacheCallbacks(), SharedInvalidationMessage::cat, CatalogCacheFlushCatalog(), CatalogCacheIdInvalidate(), SharedInvalCatalogMsg::catId, SharedInvalidationMessage::cc, SharedInvalRelmapMsg::dbId, SharedInvalRelcacheMsg::dbId, SharedInvalCatalogMsg::dbId, SharedInvalCatcacheMsg::dbId, elog, FATAL, RELCACHECALLBACK::function, SharedInvalCatcacheMsg::hashValue, i, SharedInvalCatcacheMsg::id, SharedInvalidationMessage::id, InvalidOid, MyDatabaseId, RelFileNodeBackend::node, SharedInvalidationMessage::rc, RelationCacheInvalidateEntry(), RelationMapInvalidate(), relcache_callback_count, relcache_callback_list, SharedInvalRelcacheMsg::relId, SharedInvalidationMessage::rm, SharedInvalSmgrMsg::rnode, SHAREDINVALCATALOG_ID, SHAREDINVALRELCACHE_ID, SHAREDINVALRELMAP_ID, SHAREDINVALSMGR_ID, SharedInvalidationMessage::sm, and smgrclosenode().
Referenced by AcceptInvalidationMessages(), AtEOSubXact_Inval(), AtEOXact_Inval(), and CommandEndInvalidationMessages().
{
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);
}
| static void MakeSharedInvalidMessagesArray | ( | const SharedInvalidationMessage * | msgs, | |
| int | n | |||
| ) | [static] |
Definition at line 680 of file inval.c.
References maxSharedInvalidMessagesArray, NULL, numSharedInvalidMessagesArray, palloc(), and repalloc().
Referenced by xactGetCommittedInvalidationMessages().
{
/*
* Initialise array first time through in each commit
*/
if (SharedInvalidMessagesArray == NULL)
{
maxSharedInvalidMessagesArray = FIRSTCHUNKSIZE;
numSharedInvalidMessagesArray = 0;
/*
* Although this is being palloc'd we don't actually free it directly.
* We're so close to EOXact that we now we're going to lose it anyhow.
*/
SharedInvalidMessagesArray = palloc(maxSharedInvalidMessagesArray
* sizeof(SharedInvalidationMessage));
}
if ((numSharedInvalidMessagesArray + n) > maxSharedInvalidMessagesArray)
{
while ((numSharedInvalidMessagesArray + n) > maxSharedInvalidMessagesArray)
maxSharedInvalidMessagesArray *= 2;
SharedInvalidMessagesArray = repalloc(SharedInvalidMessagesArray,
maxSharedInvalidMessagesArray
* sizeof(SharedInvalidationMessage));
}
/*
* Append the next chunk onto the array
*/
memcpy(SharedInvalidMessagesArray + numSharedInvalidMessagesArray,
msgs, n * sizeof(SharedInvalidationMessage));
numSharedInvalidMessagesArray += n;
}
| void PostPrepare_Inval | ( | void | ) |
Definition at line 653 of file inval.c.
References AtEOXact_Inval().
Referenced by PrepareTransaction().
{
AtEOXact_Inval(false);
}
| void ProcessCommittedInvalidationMessages | ( | SharedInvalidationMessage * | msgs, | |
| int | nmsgs, | |||
| bool | RelcacheInitFileInval, | |||
| Oid | dbid, | |||
| Oid | tsid | |||
| ) |
Definition at line 777 of file inval.c.
References DatabasePath, DEBUG4, elog, GetDatabasePath(), pfree(), RelationCacheInitFilePostInvalidate(), RelationCacheInitFilePreInvalidate(), SendSharedInvalidMessages(), and trace_recovery().
Referenced by xact_redo_commit_internal().
{
if (nmsgs <= 0)
return;
elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
(RelcacheInitFileInval ? " and relcache file invalidation" : ""));
if (RelcacheInitFileInval)
{
/*
* RelationCacheInitFilePreInvalidate requires DatabasePath to be set,
* but we should not use SetDatabasePath during recovery, since it is
* intended to be used only once by normal backends. Hence, a quick
* hack: set DatabasePath directly then unset after use.
*/
DatabasePath = GetDatabasePath(dbid, tsid);
elog(trace_recovery(DEBUG4), "removing relcache init file in \"%s\"",
DatabasePath);
RelationCacheInitFilePreInvalidate();
pfree(DatabasePath);
DatabasePath = NULL;
}
SendSharedInvalidMessages(msgs, nmsgs);
if (RelcacheInitFileInval)
RelationCacheInitFilePostInvalidate();
}
| static void ProcessInvalidationMessages | ( | InvalidationListHeader * | hdr, | |
| void(*)(SharedInvalidationMessage *msg) | func | |||
| ) | [static] |
Definition at line 394 of file inval.c.
References InvalidationListHeader::cclist, ProcessMessageList, and InvalidationListHeader::rclist.
Referenced by AtEOSubXact_Inval(), AtEOXact_Inval(), and CommandEndInvalidationMessages().
{
ProcessMessageList(hdr->cclist, func(msg));
ProcessMessageList(hdr->rclist, func(msg));
}
| static void ProcessInvalidationMessagesMulti | ( | InvalidationListHeader * | hdr, | |
| void(*)(const SharedInvalidationMessage *msgs, int n) | func | |||
| ) | [static] |
Definition at line 406 of file inval.c.
References InvalidationListHeader::cclist, ProcessMessageListMulti, and InvalidationListHeader::rclist.
Referenced by AtEOXact_Inval(), and xactGetCommittedInvalidationMessages().
{
ProcessMessageListMulti(hdr->cclist, func(msgs, n));
ProcessMessageListMulti(hdr->rclist, func(msgs, n));
}
Definition at line 438 of file inval.c.
References AddCatalogInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.
Referenced by CacheInvalidateCatalog().
{
AddCatalogInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
dbId, catId);
}
Definition at line 424 of file inval.c.
References AddCatcacheInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.
Referenced by CacheInvalidateHeapTuple().
{
AddCatcacheInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
cacheId, hashValue, dbId);
}
Definition at line 450 of file inval.c.
References AddRelcacheInvalidationMessage(), TransInvalidationInfo::CurrentCmdInvalidMsgs, GetCurrentCommandId(), RelationIdIsInInitFile(), and TransInvalidationInfo::RelcacheInitFileInval.
Referenced by CacheInvalidateHeapTuple(), CacheInvalidateRelcache(), and CacheInvalidateRelcacheByTuple().
{
AddRelcacheInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
dbId, relId);
/*
* Most of the time, relcache invalidation is associated with system
* catalog updates, but there are a few cases where it isn't. Quick hack
* to ensure that the next CommandCounterIncrement() will think that we
* need to do CommandEndInvalidationMessages().
*/
(void) GetCurrentCommandId(true);
/*
* If the relation being invalidated is one of those cached in the
* relcache init file, mark that we need to zap that file at commit.
*/
if (RelationIdIsInInitFile(relId))
transInvalInfo->RelcacheInitFileInval = true;
}
| int xactGetCommittedInvalidationMessages | ( | SharedInvalidationMessage ** | msgs, | |
| bool * | RelcacheInitFileInval | |||
| ) |
Definition at line 730 of file inval.c.
References Assert, TransInvalidationInfo::CurrentCmdInvalidMsgs, CurTransactionContext, MakeSharedInvalidMessagesArray(), MemoryContextSwitchTo(), NULL, numSharedInvalidMessagesArray, TransInvalidationInfo::parent, TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessagesMulti(), and TransInvalidationInfo::RelcacheInitFileInval.
Referenced by RecordTransactionCommit(), and StartPrepare().
{
MemoryContext oldcontext;
/* 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.
*/
*RelcacheInitFileInval = transInvalInfo->RelcacheInitFileInval;
/*
* Walk through TransInvalidationInfo to collect all the messages into a
* single contiguous array of invalidation messages. It must be contiguous
* so we can copy directly into WAL message. Maintain the order that they
* would be processed in by AtEOXact_Inval(), to ensure emulated behaviour
* in redo is as similar as possible to original. We want the same bugs,
* if any, not new ones.
*/
oldcontext = MemoryContextSwitchTo(CurTransactionContext);
ProcessInvalidationMessagesMulti(&transInvalInfo->CurrentCmdInvalidMsgs,
MakeSharedInvalidMessagesArray);
ProcessInvalidationMessagesMulti(&transInvalInfo->PriorCmdInvalidMsgs,
MakeSharedInvalidMessagesArray);
MemoryContextSwitchTo(oldcontext);
Assert(!(numSharedInvalidMessagesArray > 0 &&
SharedInvalidMessagesArray == NULL));
*msgs = SharedInvalidMessagesArray;
return numSharedInvalidMessagesArray;
}
int maxSharedInvalidMessagesArray [static] |
Definition at line 171 of file inval.c.
Referenced by MakeSharedInvalidMessagesArray().
int numSharedInvalidMessagesArray [static] |
Definition at line 170 of file inval.c.
Referenced by AtStart_Inval(), MakeSharedInvalidMessagesArray(), and xactGetCommittedInvalidationMessages().
int relcache_callback_count = 0 [static] |
Definition at line 197 of file inval.c.
Referenced by CacheRegisterRelcacheCallback(), InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().
struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS] [static] |
Referenced by CacheRegisterRelcacheCallback(), InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().
int syscache_callback_count = 0 [static] |
Definition at line 189 of file inval.c.
Referenced by CacheRegisterSyscacheCallback(), CallSyscacheCallbacks(), and InvalidateSystemCaches().
struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS] [static] |
Referenced by CacheRegisterSyscacheCallback(), CallSyscacheCallbacks(), and InvalidateSystemCaches().
TransInvalidationInfo* transInvalInfo = NULL [static] |
1.7.1