PostgreSQL Source Code git master
inval.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/htup_details.h"
#include "access/xact.h"
#include "access/xloginsert.h"
#include "catalog/catalog.h"
#include "catalog/pg_constraint.h"
#include "miscadmin.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
#include "utils/catcache.h"
#include "utils/inval.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/relmapper.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for inval.c:

Go to the source code of this file.

Data Structures

struct  InvalMessageArray
 
struct  InvalidationMsgsGroup
 
struct  InvalidationInfo
 
struct  TransInvalidationInfo
 
struct  SYSCACHECALLBACK
 
struct  RELCACHECALLBACK
 

Macros

#define CatCacheMsgs   0
 
#define RelCacheMsgs   1
 
#define SetSubGroupToFollow(targetgroup, priorgroup, subgroup)
 
#define SetGroupToFollow(targetgroup, priorgroup)
 
#define NumMessagesInSubGroup(group, subgroup)    ((group)->nextmsg[subgroup] - (group)->firstmsg[subgroup])
 
#define NumMessagesInGroup(group)
 
#define MAX_SYSCACHE_CALLBACKS   64
 
#define MAX_RELCACHE_CALLBACKS   10
 
#define ProcessMessageSubGroup(group, subgroup, codeFragment)
 
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
 

Typedefs

typedef struct InvalMessageArray InvalMessageArray
 
typedef struct InvalidationMsgsGroup InvalidationMsgsGroup
 
typedef struct InvalidationInfo InvalidationInfo
 
typedef struct TransInvalidationInfo TransInvalidationInfo
 

Functions

static void AddInvalidationMessage (InvalidationMsgsGroup *group, int subgroup, const SharedInvalidationMessage *msg)
 
static void AppendInvalidationMessageSubGroup (InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src, int subgroup)
 
static void AddCatcacheInvalidationMessage (InvalidationMsgsGroup *group, int id, uint32 hashValue, Oid dbId)
 
static void AddCatalogInvalidationMessage (InvalidationMsgsGroup *group, Oid dbId, Oid catId)
 
static void AddRelcacheInvalidationMessage (InvalidationMsgsGroup *group, Oid dbId, Oid relId)
 
static void AddSnapshotInvalidationMessage (InvalidationMsgsGroup *group, Oid dbId, Oid relId)
 
static void AppendInvalidationMessages (InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src)
 
static void ProcessInvalidationMessages (InvalidationMsgsGroup *group, void(*func)(SharedInvalidationMessage *msg))
 
static void ProcessInvalidationMessagesMulti (InvalidationMsgsGroup *group, void(*func)(const SharedInvalidationMessage *msgs, int n))
 
static void RegisterCatcacheInvalidation (int cacheId, uint32 hashValue, Oid dbId, void *context)
 
static void RegisterCatalogInvalidation (InvalidationInfo *info, Oid dbId, Oid catId)
 
static void RegisterRelcacheInvalidation (InvalidationInfo *info, Oid dbId, Oid relId)
 
static void RegisterSnapshotInvalidation (InvalidationInfo *info, Oid dbId, Oid relId)
 
static InvalidationInfoPrepareInvalidationState (void)
 
static InvalidationInfoPrepareInplaceInvalidationState (void)
 
void InvalidateSystemCachesExtended (bool debug_discard)
 
void LocalExecuteInvalidationMessage (SharedInvalidationMessage *msg)
 
void InvalidateSystemCaches (void)
 
void AcceptInvalidationMessages (void)
 
void PostPrepare_Inval (void)
 
int xactGetCommittedInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
int inplaceGetInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
void ProcessCommittedInvalidationMessages (SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
 
void AtEOXact_Inval (bool isCommit)
 
void PreInplace_Inval (void)
 
void AtInplace_Inval (void)
 
void ForgetInplace_Inval (void)
 
void AtEOSubXact_Inval (bool isCommit)
 
void CommandEndInvalidationMessages (void)
 
static void CacheInvalidateHeapTupleCommon (Relation relation, HeapTuple tuple, HeapTuple newtuple, InvalidationInfo *(*prepare_callback)(void))
 
void CacheInvalidateHeapTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple)
 
void CacheInvalidateHeapTupleInplace (Relation relation, HeapTuple tuple, HeapTuple newtuple)
 
void CacheInvalidateCatalog (Oid catalogId)
 
void CacheInvalidateRelcache (Relation relation)
 
void CacheInvalidateRelcacheAll (void)
 
void CacheInvalidateRelcacheByTuple (HeapTuple classTuple)
 
void CacheInvalidateRelcacheByRelid (Oid relid)
 
void CacheInvalidateSmgr (RelFileLocatorBackend rlocator)
 
void CacheInvalidateRelmap (Oid databaseId)
 
void CacheRegisterSyscacheCallback (int cacheid, SyscacheCallbackFunction func, Datum arg)
 
void CacheRegisterRelcacheCallback (RelcacheCallbackFunction func, Datum arg)
 
void CallSyscacheCallbacks (int cacheid, uint32 hashvalue)
 
void LogLogicalInvalidations (void)
 

Variables

static InvalMessageArray InvalMessageArrays [2]
 
static TransInvalidationInfotransInvalInfo = NULL
 
static InvalidationInfoinplaceInvalInfo = NULL
 
int debug_discard_caches = 0
 
static struct SYSCACHECALLBACK syscache_callback_list [MAX_SYSCACHE_CALLBACKS]
 
static int16 syscache_callback_links [SysCacheSize]
 
static int syscache_callback_count = 0
 
static struct RELCACHECALLBACK relcache_callback_list [MAX_RELCACHE_CALLBACKS]
 
static int relcache_callback_count = 0
 

Macro Definition Documentation

◆ CatCacheMsgs

#define CatCacheMsgs   0

Definition at line 169 of file inval.c.

◆ MAX_RELCACHE_CALLBACKS

#define MAX_RELCACHE_CALLBACKS   10

Definition at line 271 of file inval.c.

◆ MAX_SYSCACHE_CALLBACKS

#define MAX_SYSCACHE_CALLBACKS   64

Definition at line 270 of file inval.c.

◆ NumMessagesInGroup

#define NumMessagesInGroup (   group)
Value:
NumMessagesInSubGroup(group, RelCacheMsgs))
#define CatCacheMsgs
Definition: inval.c:169
#define NumMessagesInSubGroup(group, subgroup)
Definition: inval.c:202
#define RelCacheMsgs
Definition: inval.c:170

Definition at line 205 of file inval.c.

◆ NumMessagesInSubGroup

#define NumMessagesInSubGroup (   group,
  subgroup 
)     ((group)->nextmsg[subgroup] - (group)->firstmsg[subgroup])

Definition at line 202 of file inval.c.

◆ ProcessMessageSubGroup

#define ProcessMessageSubGroup (   group,
  subgroup,
  codeFragment 
)
Value:
do { \
int _msgindex = (group)->firstmsg[subgroup]; \
int _endmsg = (group)->nextmsg[subgroup]; \
for (; _msgindex < _endmsg; _msgindex++) \
{ \
SharedInvalidationMessage *msg = \
&InvalMessageArrays[subgroup].msgs[_msgindex]; \
codeFragment; \
} \
} while (0)
static InvalMessageArray InvalMessageArrays[2]
Definition: inval.c:179
SharedInvalidationMessage * msgs
Definition: inval.c:175

Definition at line 372 of file inval.c.

◆ ProcessMessageSubGroupMulti

#define ProcessMessageSubGroupMulti (   group,
  subgroup,
  codeFragment 
)
Value:
do { \
int n = NumMessagesInSubGroup(group, subgroup); \
if (n > 0) { \
SharedInvalidationMessage *msgs = \
&InvalMessageArrays[subgroup].msgs[(group)->firstmsg[subgroup]]; \
codeFragment; \
} \
} while (0)

Definition at line 390 of file inval.c.

◆ RelCacheMsgs

#define RelCacheMsgs   1

Definition at line 170 of file inval.c.

◆ SetGroupToFollow

#define SetGroupToFollow (   targetgroup,
  priorgroup 
)
Value:
do { \
SetSubGroupToFollow(targetgroup, priorgroup, CatCacheMsgs); \
SetSubGroupToFollow(targetgroup, priorgroup, RelCacheMsgs); \
} while (0)

Definition at line 196 of file inval.c.

◆ SetSubGroupToFollow

#define SetSubGroupToFollow (   targetgroup,
  priorgroup,
  subgroup 
)
Value:
do { \
(targetgroup)->firstmsg[subgroup] = \
(targetgroup)->nextmsg[subgroup] = \
(priorgroup)->nextmsg[subgroup]; \
} while (0)

Definition at line 189 of file inval.c.

Typedef Documentation

◆ InvalidationInfo

◆ InvalidationMsgsGroup

◆ InvalMessageArray

◆ TransInvalidationInfo

Function Documentation

◆ AcceptInvalidationMessages()

void AcceptInvalidationMessages ( void  )

Definition at line 863 of file inval.c.

864{
867
868 /*----------
869 * Test code to force cache flushes anytime a flush could happen.
870 *
871 * This helps detect intermittent faults caused by code that reads a cache
872 * entry and then performs an action that could invalidate the entry, but
873 * rarely actually does so. This can spot issues that would otherwise
874 * only arise with badly timed concurrent DDL, for example.
875 *
876 * The default debug_discard_caches = 0 does no forced cache flushes.
877 *
878 * If used with CLOBBER_FREED_MEMORY,
879 * debug_discard_caches = 1 (formerly known as CLOBBER_CACHE_ALWAYS)
880 * provides a fairly thorough test that the system contains no cache-flush
881 * hazards. However, it also makes the system unbelievably slow --- the
882 * regression tests take about 100 times longer than normal.
883 *
884 * If you're a glutton for punishment, try
885 * debug_discard_caches = 3 (formerly known as CLOBBER_CACHE_RECURSIVELY).
886 * This slows things by at least a factor of 10000, so I wouldn't suggest
887 * trying to run the entire regression tests that way. It's useful to try
888 * a few simple tests, to make sure that cache reload isn't subject to
889 * internal cache-flush hazards, but after you've done a few thousand
890 * recursive reloads it's unlikely you'll learn more.
891 *----------
892 */
893#ifdef DISCARD_CACHES_ENABLED
894 {
895 static int recursion_depth = 0;
896
898 {
902 }
903 }
904#endif
905}
static int recursion_depth
Definition: elog.c:149
void InvalidateSystemCachesExtended(bool debug_discard)
Definition: inval.c:731
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:762
void InvalidateSystemCaches(void)
Definition: inval.c:849
int debug_discard_caches
Definition: inval.c:258
void ReceiveSharedInvalidMessages(void(*invalFunction)(SharedInvalidationMessage *msg), void(*resetFunction)(void))
Definition: sinval.c:69

References debug_discard_caches, InvalidateSystemCaches(), InvalidateSystemCachesExtended(), LocalExecuteInvalidationMessage(), ReceiveSharedInvalidMessages(), and recursion_depth.

Referenced by apply_handle_commit_internal(), AtStart_Cache(), ConditionalLockDatabaseObject(), ConditionalLockRelation(), ConditionalLockRelationOid(), ConditionalLockSharedObject(), delay_execution_planner(), heap_inplace_update_and_unlock(), InitializeSessionUserId(), LockDatabaseObject(), LockRelation(), LockRelationId(), LockRelationOid(), LockSharedObject(), LogicalRepApplyLoop(), pgstat_init_function_usage(), ProcessCatchupInterrupt(), RangeVarGetRelidExtended(), relation_openrv(), relation_openrv_extended(), RelationBuildPartitionDesc(), RemoveRelations(), SearchSysCacheLocked1(), and write_relcache_init_file().

◆ AddCatalogInvalidationMessage()

static void AddCatalogInvalidationMessage ( InvalidationMsgsGroup group,
Oid  dbId,
Oid  catId 
)
static

Definition at line 441 of file inval.c.

443{
445
447 msg.cat.dbId = dbId;
448 msg.cat.catId = catId;
449 /* check AddCatcacheInvalidationMessage() for an explanation */
450 VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
451
453}
static void AddInvalidationMessage(InvalidationMsgsGroup *group, int subgroup, const SharedInvalidationMessage *msg)
Definition: inval.c:308
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
#define SHAREDINVALCATALOG_ID
Definition: sinval.h:67
SharedInvalCatalogMsg cat
Definition: sinval.h:117

References AddInvalidationMessage(), SharedInvalidationMessage::cat, CatCacheMsgs, SharedInvalCatalogMsg::catId, SharedInvalCatalogMsg::dbId, SharedInvalCatalogMsg::id, SHAREDINVALCATALOG_ID, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by RegisterCatalogInvalidation().

◆ AddCatcacheInvalidationMessage()

static void AddCatcacheInvalidationMessage ( InvalidationMsgsGroup group,
int  id,
uint32  hashValue,
Oid  dbId 
)
static

Definition at line 413 of file inval.c.

415{
417
418 Assert(id < CHAR_MAX);
419 msg.cc.id = (int8) id;
420 msg.cc.dbId = dbId;
421 msg.cc.hashValue = hashValue;
422
423 /*
424 * Define padding bytes in SharedInvalidationMessage structs to be
425 * defined. Otherwise the sinvaladt.c ringbuffer, which is accessed by
426 * multiple processes, will cause spurious valgrind warnings about
427 * undefined memory being used. That's because valgrind remembers the
428 * undefined bytes from the last local process's store, not realizing that
429 * another process has written since, filling the previously uninitialized
430 * bytes
431 */
432 VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
433
435}
#define Assert(condition)
Definition: c.h:815
int8_t int8
Definition: c.h:482
SharedInvalCatcacheMsg cc
Definition: sinval.h:116

References AddInvalidationMessage(), Assert, CatCacheMsgs, SharedInvalidationMessage::cc, SharedInvalCatcacheMsg::dbId, SharedInvalCatcacheMsg::hashValue, SharedInvalCatcacheMsg::id, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by RegisterCatcacheInvalidation().

◆ AddInvalidationMessage()

static void AddInvalidationMessage ( InvalidationMsgsGroup group,
int  subgroup,
const SharedInvalidationMessage msg 
)
static

Definition at line 308 of file inval.c.

310{
311 InvalMessageArray *ima = &InvalMessageArrays[subgroup];
312 int nextindex = group->nextmsg[subgroup];
313
314 if (nextindex >= ima->maxmsgs)
315 {
316 if (ima->msgs == NULL)
317 {
318 /* Create new storage array in TopTransactionContext */
319 int reqsize = 32; /* arbitrary */
320
323 reqsize * sizeof(SharedInvalidationMessage));
324 ima->maxmsgs = reqsize;
325 Assert(nextindex == 0);
326 }
327 else
328 {
329 /* Enlarge storage array */
330 int reqsize = 2 * ima->maxmsgs;
331
333 repalloc(ima->msgs,
334 reqsize * sizeof(SharedInvalidationMessage));
335 ima->maxmsgs = reqsize;
336 }
337 }
338 /* Okay, add message to current group */
339 ima->msgs[nextindex] = *msg;
340 group->nextmsg[subgroup]++;
341}
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
MemoryContext TopTransactionContext
Definition: mcxt.c:154
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541

References Assert, InvalMessageArrays, InvalMessageArray::maxmsgs, MemoryContextAlloc(), InvalMessageArray::msgs, InvalidationMsgsGroup::nextmsg, repalloc(), and TopTransactionContext.

Referenced by AddCatalogInvalidationMessage(), AddCatcacheInvalidationMessage(), AddRelcacheInvalidationMessage(), and AddSnapshotInvalidationMessage().

◆ AddRelcacheInvalidationMessage()

static void AddRelcacheInvalidationMessage ( InvalidationMsgsGroup group,
Oid  dbId,
Oid  relId 
)
static

Definition at line 459 of file inval.c.

461{
463
464 /*
465 * Don't add a duplicate item. We assume dbId need not be checked because
466 * it will never change. InvalidOid for relId means all relations so we
467 * don't need to add individual ones when it is present.
468 */
470 if (msg->rc.id == SHAREDINVALRELCACHE_ID &&
471 (msg->rc.relId == relId ||
472 msg->rc.relId == InvalidOid))
473 return);
474
475 /* OK, add the item */
477 msg.rc.dbId = dbId;
478 msg.rc.relId = relId;
479 /* check AddCatcacheInvalidationMessage() for an explanation */
480 VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
481
483}
#define ProcessMessageSubGroup(group, subgroup, codeFragment)
Definition: inval.c:372
#define InvalidOid
Definition: postgres_ext.h:37
#define SHAREDINVALRELCACHE_ID
Definition: sinval.h:76
SharedInvalRelcacheMsg rc
Definition: sinval.h:118

References AddInvalidationMessage(), SharedInvalRelcacheMsg::dbId, SharedInvalRelcacheMsg::id, InvalidOid, ProcessMessageSubGroup, SharedInvalidationMessage::rc, RelCacheMsgs, SharedInvalRelcacheMsg::relId, SHAREDINVALRELCACHE_ID, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by RegisterRelcacheInvalidation().

◆ AddSnapshotInvalidationMessage()

static void AddSnapshotInvalidationMessage ( InvalidationMsgsGroup group,
Oid  dbId,
Oid  relId 
)
static

Definition at line 491 of file inval.c.

493{
495
496 /* Don't add a duplicate item */
497 /* We assume dbId need not be checked because it will never change */
499 if (msg->sn.id == SHAREDINVALSNAPSHOT_ID &&
500 msg->sn.relId == relId)
501 return);
502
503 /* OK, add the item */
505 msg.sn.dbId = dbId;
506 msg.sn.relId = relId;
507 /* check AddCatcacheInvalidationMessage() for an explanation */
508 VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
509
511}
#define SHAREDINVALSNAPSHOT_ID
Definition: sinval.h:104
SharedInvalSnapshotMsg sn
Definition: sinval.h:121

References AddInvalidationMessage(), SharedInvalSnapshotMsg::dbId, SharedInvalSnapshotMsg::id, ProcessMessageSubGroup, RelCacheMsgs, SharedInvalSnapshotMsg::relId, SHAREDINVALSNAPSHOT_ID, SharedInvalidationMessage::sn, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by RegisterSnapshotInvalidation().

◆ AppendInvalidationMessages()

static void AppendInvalidationMessages ( InvalidationMsgsGroup dest,
InvalidationMsgsGroup src 
)
static

Definition at line 518 of file inval.c.

520{
523}
static void AppendInvalidationMessageSubGroup(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src, int subgroup)
Definition: inval.c:348

References AppendInvalidationMessageSubGroup(), CatCacheMsgs, generate_unaccent_rules::dest, and RelCacheMsgs.

Referenced by AtEOSubXact_Inval(), AtEOXact_Inval(), and CommandEndInvalidationMessages().

◆ AppendInvalidationMessageSubGroup()

static void AppendInvalidationMessageSubGroup ( InvalidationMsgsGroup dest,
InvalidationMsgsGroup src,
int  subgroup 
)
static

Definition at line 348 of file inval.c.

351{
352 /* Messages must be adjacent in main array */
353 Assert(dest->nextmsg[subgroup] == src->firstmsg[subgroup]);
354
355 /* ... which makes this easy: */
356 dest->nextmsg[subgroup] = src->nextmsg[subgroup];
357
358 /*
359 * This is handy for some callers and irrelevant for others. But we do it
360 * always, reasoning that it's bad to leave different groups pointing at
361 * the same fragment of the message array.
362 */
363 SetSubGroupToFollow(src, dest, subgroup);
364}
#define SetSubGroupToFollow(targetgroup, priorgroup, subgroup)
Definition: inval.c:189

References Assert, generate_unaccent_rules::dest, InvalidationMsgsGroup::firstmsg, InvalidationMsgsGroup::nextmsg, and SetSubGroupToFollow.

Referenced by AppendInvalidationMessages().

◆ AtEOSubXact_Inval()

void AtEOSubXact_Inval ( bool  isCommit)

Definition at line 1235 of file inval.c.

1236{
1237 int my_level;
1238 TransInvalidationInfo *myInfo;
1239
1240 /*
1241 * Successful inplace update must clear this, but we clear it on abort.
1242 * Inplace updates allocate this in CurrentMemoryContext, which has
1243 * lifespan <= subtransaction lifespan. Hence, don't free it explicitly.
1244 */
1245 if (isCommit)
1246 Assert(inplaceInvalInfo == NULL);
1247 else
1248 inplaceInvalInfo = NULL;
1249
1250 /* Quick exit if no transactional messages. */
1251 myInfo = transInvalInfo;
1252 if (myInfo == NULL)
1253 return;
1254
1255 /* Also bail out quickly if messages are not for this level. */
1256 my_level = GetCurrentTransactionNestLevel();
1257 if (myInfo->my_level != my_level)
1258 {
1259 Assert(myInfo->my_level < my_level);
1260 return;
1261 }
1262
1263 if (isCommit)
1264 {
1265 /* If CurrentCmdInvalidMsgs still has anything, fix it */
1267
1268 /*
1269 * We create invalidation stack entries lazily, so the parent might
1270 * not have one. Instead of creating one, moving all the data over,
1271 * and then freeing our own, we can just adjust the level of our own
1272 * entry.
1273 */
1274 if (myInfo->parent == NULL || myInfo->parent->my_level < my_level - 1)
1275 {
1276 myInfo->my_level--;
1277 return;
1278 }
1279
1280 /*
1281 * Pass up my inval messages to parent. Notice that we stick them in
1282 * PriorCmdInvalidMsgs, not CurrentCmdInvalidMsgs, since they've
1283 * already been locally processed. (This would trigger the Assert in
1284 * AppendInvalidationMessageSubGroup if the parent's
1285 * CurrentCmdInvalidMsgs isn't empty; but we already checked that in
1286 * PrepareInvalidationState.)
1287 */
1289 &myInfo->PriorCmdInvalidMsgs);
1290
1291 /* Must readjust parent's CurrentCmdInvalidMsgs indexes now */
1293 &myInfo->parent->PriorCmdInvalidMsgs);
1294
1295 /* Pending relcache inval becomes parent's problem too */
1296 if (myInfo->ii.RelcacheInitFileInval)
1297 myInfo->parent->ii.RelcacheInitFileInval = true;
1298
1299 /* Pop the transaction state stack */
1300 transInvalInfo = myInfo->parent;
1301
1302 /* Need not free anything else explicitly */
1303 pfree(myInfo);
1304 }
1305 else
1306 {
1309
1310 /* Pop the transaction state stack */
1311 transInvalInfo = myInfo->parent;
1312
1313 /* Need not free anything else explicitly */
1314 pfree(myInfo);
1315 }
1316}
static void ProcessInvalidationMessages(InvalidationMsgsGroup *group, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:532
static InvalidationInfo * inplaceInvalInfo
Definition: inval.c:255
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:253
static void AppendInvalidationMessages(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src)
Definition: inval.c:518
#define SetGroupToFollow(targetgroup, priorgroup)
Definition: inval.c:196
void CommandEndInvalidationMessages(void)
Definition: inval.c:1334
void pfree(void *pointer)
Definition: mcxt.c:1521
bool RelcacheInitFileInval
Definition: inval.c:234
InvalidationMsgsGroup CurrentCmdInvalidMsgs
Definition: inval.c:231
struct TransInvalidationInfo * parent
Definition: inval.c:247
struct InvalidationInfo ii
Definition: inval.c:241
InvalidationMsgsGroup PriorCmdInvalidMsgs
Definition: inval.c:244
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:928

References AppendInvalidationMessages(), Assert, CommandEndInvalidationMessages(), InvalidationInfo::CurrentCmdInvalidMsgs, GetCurrentTransactionNestLevel(), TransInvalidationInfo::ii, inplaceInvalInfo, LocalExecuteInvalidationMessage(), TransInvalidationInfo::my_level, TransInvalidationInfo::parent, pfree(), TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessages(), InvalidationInfo::RelcacheInitFileInval, SetGroupToFollow, and transInvalInfo.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_Inval()

void AtEOXact_Inval ( bool  isCommit)

Definition at line 1126 of file inval.c.

1127{
1128 inplaceInvalInfo = NULL;
1129
1130 /* Quick exit if no transactional messages */
1131 if (transInvalInfo == NULL)
1132 return;
1133
1134 /* Must be at top of stack */
1136
1137 if (isCommit)
1138 {
1139 /*
1140 * Relcache init file invalidation requires processing both before and
1141 * after we send the SI messages. However, we need not do anything
1142 * unless we committed.
1143 */
1146
1149
1152
1155 }
1156 else
1157 {
1160 }
1161
1162 /* Need not free anything explicitly */
1163 transInvalInfo = NULL;
1164}
static void ProcessInvalidationMessagesMulti(InvalidationMsgsGroup *group, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:544
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6805
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:6780
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:47

References AppendInvalidationMessages(), Assert, InvalidationInfo::CurrentCmdInvalidMsgs, TransInvalidationInfo::ii, inplaceInvalInfo, LocalExecuteInvalidationMessage(), TransInvalidationInfo::my_level, TransInvalidationInfo::parent, TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessages(), ProcessInvalidationMessagesMulti(), RelationCacheInitFilePostInvalidate(), RelationCacheInitFilePreInvalidate(), InvalidationInfo::RelcacheInitFileInval, SendSharedInvalidMessages(), and transInvalInfo.

Referenced by AbortTransaction(), CommitTransaction(), and PostPrepare_Inval().

◆ AtInplace_Inval()

◆ CacheInvalidateCatalog()

void CacheInvalidateCatalog ( Oid  catalogId)

Definition at line 1530 of file inval.c.

1531{
1532 Oid databaseId;
1533
1534 if (IsSharedRelation(catalogId))
1535 databaseId = InvalidOid;
1536 else
1537 databaseId = MyDatabaseId;
1538
1540 databaseId, catalogId);
1541}
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:273
Oid MyDatabaseId
Definition: globals.c:93
static InvalidationInfo * PrepareInvalidationState(void)
Definition: inval.c:629
static void RegisterCatalogInvalidation(InvalidationInfo *info, Oid dbId, Oid catId)
Definition: inval.c:579
unsigned int Oid
Definition: postgres_ext.h:32

References InvalidOid, IsSharedRelation(), MyDatabaseId, PrepareInvalidationState(), and RegisterCatalogInvalidation().

Referenced by finish_heap_swap().

◆ CacheInvalidateHeapTuple()

void CacheInvalidateHeapTuple ( Relation  relation,
HeapTuple  tuple,
HeapTuple  newtuple 
)

Definition at line 1493 of file inval.c.

1496{
1497 CacheInvalidateHeapTupleCommon(relation, tuple, newtuple,
1499}
static void CacheInvalidateHeapTupleCommon(Relation relation, HeapTuple tuple, HeapTuple newtuple, InvalidationInfo *(*prepare_callback)(void))
Definition: inval.c:1361

References CacheInvalidateHeapTupleCommon(), and PrepareInvalidationState().

Referenced by AlterDomainAddConstraint(), AlterDomainDropConstraint(), heap_delete(), heap_inplace_update_and_unlock(), heap_insert(), heap_multi_insert(), and heap_update().

◆ CacheInvalidateHeapTupleCommon()

static void CacheInvalidateHeapTupleCommon ( Relation  relation,
HeapTuple  tuple,
HeapTuple  newtuple,
InvalidationInfo *(*)(void)  prepare_callback 
)
static

Definition at line 1361 of file inval.c.

1365{
1366 InvalidationInfo *info;
1367 Oid tupleRelId;
1368 Oid databaseId;
1369 Oid relationId;
1370
1371 /* Do nothing during bootstrap */
1373 return;
1374
1375 /*
1376 * We only need to worry about invalidation for tuples that are in system
1377 * catalogs; user-relation tuples are never in catcaches and can't affect
1378 * the relcache either.
1379 */
1380 if (!IsCatalogRelation(relation))
1381 return;
1382
1383 /*
1384 * IsCatalogRelation() will return true for TOAST tables of system
1385 * catalogs, but we don't care about those, either.
1386 */
1387 if (IsToastRelation(relation))
1388 return;
1389
1390 /* Allocate any required resources. */
1391 info = prepare_callback();
1392
1393 /*
1394 * First let the catcache do its thing
1395 */
1396 tupleRelId = RelationGetRelid(relation);
1397 if (RelationInvalidatesSnapshotsOnly(tupleRelId))
1398 {
1399 databaseId = IsSharedRelation(tupleRelId) ? InvalidOid : MyDatabaseId;
1400 RegisterSnapshotInvalidation(info, databaseId, tupleRelId);
1401 }
1402 else
1403 PrepareToInvalidateCacheTuple(relation, tuple, newtuple,
1405 (void *) info);
1406
1407 /*
1408 * Now, is this tuple one of the primary definers of a relcache entry? See
1409 * comments in file header for deeper explanation.
1410 *
1411 * Note we ignore newtuple here; we assume an update cannot move a tuple
1412 * from being part of one relcache entry to being part of another.
1413 */
1414 if (tupleRelId == RelationRelationId)
1415 {
1416 Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple);
1417
1418 relationId = classtup->oid;
1419 if (classtup->relisshared)
1420 databaseId = InvalidOid;
1421 else
1422 databaseId = MyDatabaseId;
1423 }
1424 else if (tupleRelId == AttributeRelationId)
1425 {
1427
1428 relationId = atttup->attrelid;
1429
1430 /*
1431 * KLUGE ALERT: we always send the relcache event with MyDatabaseId,
1432 * even if the rel in question is shared (which we can't easily tell).
1433 * This essentially means that only backends in this same database
1434 * will react to the relcache flush request. This is in fact
1435 * appropriate, since only those backends could see our pg_attribute
1436 * change anyway. It looks a bit ugly though. (In practice, shared
1437 * relations can't have schema changes after bootstrap, so we should
1438 * never come here for a shared rel anyway.)
1439 */
1440 databaseId = MyDatabaseId;
1441 }
1442 else if (tupleRelId == IndexRelationId)
1443 {
1444 Form_pg_index indextup = (Form_pg_index) GETSTRUCT(tuple);
1445
1446 /*
1447 * When a pg_index row is updated, we should send out a relcache inval
1448 * for the index relation. As above, we don't know the shared status
1449 * of the index, but in practice it doesn't matter since indexes of
1450 * shared catalogs can't have such updates.
1451 */
1452 relationId = indextup->indexrelid;
1453 databaseId = MyDatabaseId;
1454 }
1455 else if (tupleRelId == ConstraintRelationId)
1456 {
1457 Form_pg_constraint constrtup = (Form_pg_constraint) GETSTRUCT(tuple);
1458
1459 /*
1460 * Foreign keys are part of relcache entries, too, so send out an
1461 * inval for the table that the FK applies to.
1462 */
1463 if (constrtup->contype == CONSTRAINT_FOREIGN &&
1464 OidIsValid(constrtup->conrelid))
1465 {
1466 relationId = constrtup->conrelid;
1467 databaseId = MyDatabaseId;
1468 }
1469 else
1470 return;
1471 }
1472 else
1473 return;
1474
1475 /*
1476 * Yes. We need to register a relcache invalidation event.
1477 */
1478 RegisterRelcacheInvalidation(info, databaseId, relationId);
1479}
#define OidIsValid(objectId)
Definition: c.h:732
bool IsToastRelation(Relation relation)
Definition: catalog.c:175
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:103
void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid, void *), void *context)
Definition: catcache.c:2354
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static void RegisterRelcacheInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
Definition: inval.c:590
static void RegisterCatcacheInvalidation(int cacheId, uint32 hashValue, Oid dbId, void *context)
Definition: inval.c:562
static void RegisterSnapshotInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
Definition: inval.c:619
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
FormData_pg_constraint * Form_pg_constraint
FormData_pg_index * Form_pg_index
Definition: pg_index.h:70
#define RelationGetRelid(relation)
Definition: rel.h:505
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:722

References GETSTRUCT, InvalidOid, IsBootstrapProcessingMode, IsCatalogRelation(), IsSharedRelation(), IsToastRelation(), MyDatabaseId, OidIsValid, PrepareToInvalidateCacheTuple(), RegisterCatcacheInvalidation(), RegisterRelcacheInvalidation(), RegisterSnapshotInvalidation(), RelationGetRelid, and RelationInvalidatesSnapshotsOnly().

Referenced by CacheInvalidateHeapTuple(), and CacheInvalidateHeapTupleInplace().

◆ CacheInvalidateHeapTupleInplace()

void CacheInvalidateHeapTupleInplace ( Relation  relation,
HeapTuple  tuple,
HeapTuple  newtuple 
)

Definition at line 1510 of file inval.c.

1513{
1514 CacheInvalidateHeapTupleCommon(relation, tuple, newtuple,
1516}
static InvalidationInfo * PrepareInplaceInvalidationState(void)
Definition: inval.c:698

References CacheInvalidateHeapTupleCommon(), and PrepareInplaceInvalidationState().

Referenced by heap_inplace_lock().

◆ CacheInvalidateRelcache()

◆ CacheInvalidateRelcacheAll()

◆ CacheInvalidateRelcacheByRelid()

void CacheInvalidateRelcacheByRelid ( Oid  relid)

Definition at line 1609 of file inval.c.

1610{
1611 HeapTuple tup;
1612
1613 tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1614 if (!HeapTupleIsValid(tup))
1615 elog(ERROR, "cache lookup failed for relation %u", relid);
1617 ReleaseSysCache(tup);
1618}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1587
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References CacheInvalidateRelcacheByTuple(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), and SearchSysCache1().

Referenced by ATExecAlterConstraint(), ATExecAttachPartition(), DefineIndex(), DetachPartitionFinalize(), heap_drop_with_catalog(), InvalidatePublicationRels(), ReindexRelationConcurrently(), RemoveStatisticsById(), and StorePartitionBound().

◆ CacheInvalidateRelcacheByTuple()

void CacheInvalidateRelcacheByTuple ( HeapTuple  classTuple)

Definition at line 1587 of file inval.c.

1588{
1589 Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple);
1590 Oid databaseId;
1591 Oid relationId;
1592
1593 relationId = classtup->oid;
1594 if (classtup->relisshared)
1595 databaseId = InvalidOid;
1596 else
1597 databaseId = MyDatabaseId;
1599 databaseId, relationId);
1600}

References GETSTRUCT, InvalidOid, MyDatabaseId, PrepareInvalidationState(), and RegisterRelcacheInvalidation().

Referenced by CacheInvalidateRelcacheByRelid(), copy_table_data(), CreateTriggerFiringOn(), index_update_stats(), RemoveRoleFromObjectPolicy(), SetRelationHasSubclass(), SetRelationRuleStatus(), and swap_relation_files().

◆ CacheInvalidateRelmap()

void CacheInvalidateRelmap ( Oid  databaseId)

Definition at line 1677 of file inval.c.

1678{
1680
1682 msg.rm.dbId = databaseId;
1683 /* check AddCatcacheInvalidationMessage() for an explanation */
1684 VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1685
1687}
#define SHAREDINVALRELMAP_ID
Definition: sinval.h:96
SharedInvalRelmapMsg rm
Definition: sinval.h:120

References SharedInvalRelmapMsg::dbId, SharedInvalRelmapMsg::id, SharedInvalidationMessage::rm, SendSharedInvalidMessages(), SHAREDINVALRELMAP_ID, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by write_relmap_file().

◆ CacheInvalidateSmgr()

void CacheInvalidateSmgr ( RelFileLocatorBackend  rlocator)

Definition at line 1647 of file inval.c.

1648{
1650
1651 msg.sm.id = SHAREDINVALSMGR_ID;
1652 msg.sm.backend_hi = rlocator.backend >> 16;
1653 msg.sm.backend_lo = rlocator.backend & 0xffff;
1654 msg.sm.rlocator = rlocator.locator;
1655 /* check AddCatcacheInvalidationMessage() for an explanation */
1656 VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1657
1659}
#define SHAREDINVALSMGR_ID
Definition: sinval.h:85
RelFileLocator locator
uint16 backend_lo
Definition: sinval.h:92
RelFileLocator rlocator
Definition: sinval.h:93
SharedInvalSmgrMsg sm
Definition: sinval.h:119

References RelFileLocatorBackend::backend, SharedInvalSmgrMsg::backend_hi, SharedInvalSmgrMsg::backend_lo, SharedInvalSmgrMsg::id, RelFileLocatorBackend::locator, SharedInvalSmgrMsg::rlocator, SendSharedInvalidMessages(), SHAREDINVALSMGR_ID, SharedInvalidationMessage::sm, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by smgrdounlinkall(), smgrtruncate(), and vm_extend().

◆ CacheRegisterRelcacheCallback()

void CacheRegisterRelcacheCallback ( RelcacheCallbackFunction  func,
Datum  arg 
)

Definition at line 1746 of file inval.c.

1748{
1750 elog(FATAL, "out of relcache_callback_list slots");
1751
1754
1756}
#define FATAL
Definition: elog.h:41
static int relcache_callback_count
Definition: inval.c:291
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
#define MAX_RELCACHE_CALLBACKS
Definition: inval.c:271
void * arg
RelcacheCallbackFunction function
Definition: inval.c:287

References RELCACHECALLBACK::arg, arg, elog, FATAL, RELCACHECALLBACK::function, MAX_RELCACHE_CALLBACKS, relcache_callback_count, and relcache_callback_list.

Referenced by init_rel_sync_cache(), InitializeRelfilenumberMap(), InitPlanCache(), logicalrep_partmap_init(), logicalrep_relmap_init(), and lookup_type_cache().

◆ CacheRegisterSyscacheCallback()

void CacheRegisterSyscacheCallback ( int  cacheid,
SyscacheCallbackFunction  func,
Datum  arg 
)

Definition at line 1704 of file inval.c.

1707{
1708 if (cacheid < 0 || cacheid >= SysCacheSize)
1709 elog(FATAL, "invalid cache ID: %d", cacheid);
1711 elog(FATAL, "out of syscache_callback_list slots");
1712
1713 if (syscache_callback_links[cacheid] == 0)
1714 {
1715 /* first callback for this cache */
1717 }
1718 else
1719 {
1720 /* add to end of chain, so that older callbacks are called first */
1721 int i = syscache_callback_links[cacheid] - 1;
1722
1723 while (syscache_callback_list[i].link > 0)
1726 }
1727
1732
1734}
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
#define MAX_SYSCACHE_CALLBACKS
Definition: inval.c:270
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:281
static int syscache_callback_count
Definition: inval.c:283
int i
Definition: isn.c:72
SyscacheCallbackFunction function
Definition: inval.c:277
int16 link
Definition: inval.c:276

References SYSCACHECALLBACK::arg, arg, elog, FATAL, SYSCACHECALLBACK::function, i, SYSCACHECALLBACK::id, SYSCACHECALLBACK::link, MAX_SYSCACHE_CALLBACKS, syscache_callback_count, syscache_callback_links, and syscache_callback_list.

Referenced by BuildEventTriggerCache(), find_oper_cache_entry(), GetConnection(), init_rel_sync_cache(), init_ts_config_cache(), initialize_acl(), InitializeAttoptCache(), InitializeLogRepWorker(), InitializeSearchPath(), InitializeShippableCache(), InitializeTableSpaceCache(), InitPlanCache(), lookup_proof_cache(), lookup_ts_dictionary_cache(), lookup_ts_parser_cache(), lookup_type_cache(), ParallelApplyWorkerMain(), pgoutput_startup(), ri_InitHashTables(), SetupApplyOrSyncWorker(), and superuser_arg().

◆ CallSyscacheCallbacks()

void CallSyscacheCallbacks ( int  cacheid,
uint32  hashvalue 
)

Definition at line 1765 of file inval.c.

1766{
1767 int i;
1768
1769 if (cacheid < 0 || cacheid >= SysCacheSize)
1770 elog(ERROR, "invalid cache ID: %d", cacheid);
1771
1772 i = syscache_callback_links[cacheid] - 1;
1773 while (i >= 0)
1774 {
1775 struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
1776
1777 Assert(ccitem->id == cacheid);
1778 ccitem->function(ccitem->arg, cacheid, hashvalue);
1779 i = ccitem->link - 1;
1780 }
1781}

References SYSCACHECALLBACK::arg, Assert, elog, ERROR, SYSCACHECALLBACK::function, i, SYSCACHECALLBACK::id, SYSCACHECALLBACK::link, syscache_callback_links, and syscache_callback_list.

Referenced by CatalogCacheFlushCatalog(), and LocalExecuteInvalidationMessage().

◆ CommandEndInvalidationMessages()

void CommandEndInvalidationMessages ( void  )

Definition at line 1334 of file inval.c.

1335{
1336 /*
1337 * You might think this shouldn't be called outside any transaction, but
1338 * bootstrap does it, and also ABORT issued when not in a transaction. So
1339 * just quietly return if no state to work on.
1340 */
1341 if (transInvalInfo == NULL)
1342 return;
1343
1346
1347 /* WAL Log per-command invalidation messages for wal_level=logical */
1350
1353}
void LogLogicalInvalidations(void)
Definition: inval.c:1792
#define XLogLogicalInfoActive()
Definition: xlog.h:126

References AppendInvalidationMessages(), InvalidationInfo::CurrentCmdInvalidMsgs, TransInvalidationInfo::ii, LocalExecuteInvalidationMessage(), LogLogicalInvalidations(), TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessages(), transInvalInfo, and XLogLogicalInfoActive.

Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().

◆ ForgetInplace_Inval()

void ForgetInplace_Inval ( void  )

Definition at line 1211 of file inval.c.

1212{
1213 inplaceInvalInfo = NULL;
1214}

References inplaceInvalInfo.

Referenced by heap_inplace_lock(), and heap_inplace_unlock().

◆ inplaceGetInvalidationMessages()

int inplaceGetInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool *  RelcacheInitFileInval 
)

Definition at line 1015 of file inval.c.

1017{
1018 SharedInvalidationMessage *msgarray;
1019 int nummsgs;
1020 int nmsgs;
1021
1022 /* Quick exit if we haven't done anything with invalidation messages. */
1023 if (inplaceInvalInfo == NULL)
1024 {
1025 *RelcacheInitFileInval = false;
1026 *msgs = NULL;
1027 return 0;
1028 }
1029
1030 *RelcacheInitFileInval = inplaceInvalInfo->RelcacheInitFileInval;
1032 *msgs = msgarray = (SharedInvalidationMessage *)
1033 palloc(nummsgs * sizeof(SharedInvalidationMessage));
1034
1035 nmsgs = 0;
1038 (memcpy(msgarray + nmsgs,
1039 msgs,
1040 n * sizeof(SharedInvalidationMessage)),
1041 nmsgs += n));
1044 (memcpy(msgarray + nmsgs,
1045 msgs,
1046 n * sizeof(SharedInvalidationMessage)),
1047 nmsgs += n));
1048 Assert(nmsgs == nummsgs);
1049
1050 return nmsgs;
1051}
#define NumMessagesInGroup(group)
Definition: inval.c:205
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
Definition: inval.c:390
void * palloc(Size size)
Definition: mcxt.c:1317

References Assert, CatCacheMsgs, InvalidationInfo::CurrentCmdInvalidMsgs, inplaceInvalInfo, NumMessagesInGroup, palloc(), ProcessMessageSubGroupMulti, InvalidationInfo::RelcacheInitFileInval, and RelCacheMsgs.

Referenced by heap_inplace_update_and_unlock().

◆ InvalidateSystemCaches()

◆ InvalidateSystemCachesExtended()

void InvalidateSystemCachesExtended ( bool  debug_discard)

Definition at line 731 of file inval.c.

732{
733 int i;
734
736 ResetCatalogCachesExt(debug_discard);
737 RelationCacheInvalidate(debug_discard); /* gets smgr and relmap too */
738
739 for (i = 0; i < syscache_callback_count; i++)
740 {
741 struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
742
743 ccitem->function(ccitem->arg, ccitem->id, 0);
744 }
745
746 for (i = 0; i < relcache_callback_count; i++)
747 {
748 struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
749
750 ccitem->function(ccitem->arg, InvalidOid);
751 }
752}
void ResetCatalogCachesExt(bool debug_discard)
Definition: catcache.c:804
void RelationCacheInvalidate(bool debug_discard)
Definition: relcache.c:2947
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:384

References SYSCACHECALLBACK::arg, RELCACHECALLBACK::arg, SYSCACHECALLBACK::function, RELCACHECALLBACK::function, i, SYSCACHECALLBACK::id, InvalidateCatalogSnapshot(), InvalidOid, RelationCacheInvalidate(), relcache_callback_count, relcache_callback_list, ResetCatalogCachesExt(), syscache_callback_count, and syscache_callback_list.

Referenced by AcceptInvalidationMessages(), and InvalidateSystemCaches().

◆ LocalExecuteInvalidationMessage()

void LocalExecuteInvalidationMessage ( SharedInvalidationMessage msg)

Definition at line 762 of file inval.c.

763{
764 if (msg->id >= 0)
765 {
766 if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
767 {
769
770 SysCacheInvalidate(msg->cc.id, msg->cc.hashValue);
771
773 }
774 }
775 else if (msg->id == SHAREDINVALCATALOG_ID)
776 {
777 if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
778 {
780
782
783 /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
784 }
785 }
786 else if (msg->id == SHAREDINVALRELCACHE_ID)
787 {
788 if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
789 {
790 int i;
791
792 if (msg->rc.relId == InvalidOid)
794 else
796
797 for (i = 0; i < relcache_callback_count; i++)
798 {
799 struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
800
801 ccitem->function(ccitem->arg, msg->rc.relId);
802 }
803 }
804 }
805 else if (msg->id == SHAREDINVALSMGR_ID)
806 {
807 /*
808 * We could have smgr entries for relations of other databases, so no
809 * short-circuit test is possible here.
810 */
811 RelFileLocatorBackend rlocator;
812
813 rlocator.locator = msg->sm.rlocator;
814 rlocator.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
815 smgrreleaserellocator(rlocator);
816 }
817 else if (msg->id == SHAREDINVALRELMAP_ID)
818 {
819 /* We only care about our own database and shared catalogs */
820 if (msg->rm.dbId == InvalidOid)
822 else if (msg->rm.dbId == MyDatabaseId)
824 }
825 else if (msg->id == SHAREDINVALSNAPSHOT_ID)
826 {
827 /* We only care about our own database and shared catalogs */
828 if (msg->sn.dbId == InvalidOid)
830 else if (msg->sn.dbId == MyDatabaseId)
832 }
833 else
834 elog(FATAL, "unrecognized SI message ID: %d", msg->id);
835}
void CatalogCacheFlushCatalog(Oid catId)
Definition: catcache.c:834
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1765
void RelationCacheInvalidateEntry(Oid relationId)
Definition: relcache.c:2891
void RelationMapInvalidate(bool shared)
Definition: relmapper.c:468
void smgrreleaserellocator(RelFileLocatorBackend rlocator)
Definition: smgr.c:382
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:698

References RELCACHECALLBACK::arg, RelFileLocatorBackend::backend, SharedInvalSmgrMsg::backend_hi, SharedInvalSmgrMsg::backend_lo, CallSyscacheCallbacks(), SharedInvalidationMessage::cat, CatalogCacheFlushCatalog(), SharedInvalCatalogMsg::catId, SharedInvalidationMessage::cc, SharedInvalCatcacheMsg::dbId, SharedInvalCatalogMsg::dbId, SharedInvalRelcacheMsg::dbId, SharedInvalRelmapMsg::dbId, SharedInvalSnapshotMsg::dbId, elog, FATAL, RELCACHECALLBACK::function, SharedInvalCatcacheMsg::hashValue, i, SharedInvalCatcacheMsg::id, SharedInvalidationMessage::id, InvalidateCatalogSnapshot(), InvalidOid, RelFileLocatorBackend::locator, MyDatabaseId, SharedInvalidationMessage::rc, RelationCacheInvalidate(), RelationCacheInvalidateEntry(), RelationMapInvalidate(), relcache_callback_count, relcache_callback_list, SharedInvalRelcacheMsg::relId, SharedInvalSmgrMsg::rlocator, SharedInvalidationMessage::rm, SHAREDINVALCATALOG_ID, SHAREDINVALRELCACHE_ID, SHAREDINVALRELMAP_ID, SHAREDINVALSMGR_ID, SHAREDINVALSNAPSHOT_ID, SharedInvalidationMessage::sm, smgrreleaserellocator(), SharedInvalidationMessage::sn, and SysCacheInvalidate().

Referenced by AcceptInvalidationMessages(), AtEOSubXact_Inval(), AtEOXact_Inval(), CommandEndInvalidationMessages(), ReorderBufferExecuteInvalidations(), and ReorderBufferImmediateInvalidation().

◆ LogLogicalInvalidations()

void LogLogicalInvalidations ( void  )

Definition at line 1792 of file inval.c.

1793{
1794 xl_xact_invals xlrec;
1795 InvalidationMsgsGroup *group;
1796 int nmsgs;
1797
1798 /* Quick exit if we haven't done anything with invalidation messages. */
1799 if (transInvalInfo == NULL)
1800 return;
1801
1803 nmsgs = NumMessagesInGroup(group);
1804
1805 if (nmsgs > 0)
1806 {
1807 /* prepare record */
1808 memset(&xlrec, 0, MinSizeOfXactInvals);
1809 xlrec.nmsgs = nmsgs;
1810
1811 /* perform insertion */
1813 XLogRegisterData((char *) (&xlrec), MinSizeOfXactInvals);
1815 XLogRegisterData((char *) msgs,
1816 n * sizeof(SharedInvalidationMessage)));
1818 XLogRegisterData((char *) msgs,
1819 n * sizeof(SharedInvalidationMessage)));
1821 }
1822}
int nmsgs
Definition: xact.h:304
#define MinSizeOfXactInvals
Definition: xact.h:307
#define XLOG_XACT_INVALIDATIONS
Definition: xact.h:175
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const char *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149

References CatCacheMsgs, InvalidationInfo::CurrentCmdInvalidMsgs, TransInvalidationInfo::ii, MinSizeOfXactInvals, xl_xact_invals::nmsgs, NumMessagesInGroup, ProcessMessageSubGroupMulti, RelCacheMsgs, transInvalInfo, XLOG_XACT_INVALIDATIONS, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by CommandEndInvalidationMessages(), and RecordTransactionCommit().

◆ PostPrepare_Inval()

void PostPrepare_Inval ( void  )

Definition at line 920 of file inval.c.

921{
922 AtEOXact_Inval(false);
923}
void AtEOXact_Inval(bool isCommit)
Definition: inval.c:1126

References AtEOXact_Inval().

Referenced by PrepareTransaction().

◆ PreInplace_Inval()

◆ PrepareInplaceInvalidationState()

static InvalidationInfo * PrepareInplaceInvalidationState ( void  )
static

Definition at line 698 of file inval.c.

699{
700 InvalidationInfo *myInfo;
701
703 /* limit of one inplace update under assembly */
704 Assert(inplaceInvalInfo == NULL);
705
706 /* gone after WAL insertion CritSection ends, so use current context */
707 myInfo = (InvalidationInfo *) palloc0(sizeof(InvalidationInfo));
708
709 /* Stash our messages past end of the transactional messages, if any. */
710 if (transInvalInfo != NULL)
713 else
714 {
719 }
720
721 inplaceInvalInfo = myInfo;
722 return myInfo;
723}
void * palloc0(Size size)
Definition: mcxt.c:1347
bool IsTransactionState(void)
Definition: xact.c:386

References Assert, CatCacheMsgs, InvalidationInfo::CurrentCmdInvalidMsgs, TransInvalidationInfo::ii, inplaceInvalInfo, InvalMessageArrays, IsTransactionState(), InvalMessageArray::maxmsgs, InvalMessageArray::msgs, palloc0(), RelCacheMsgs, SetGroupToFollow, and transInvalInfo.

Referenced by CacheInvalidateHeapTupleInplace().

◆ PrepareInvalidationState()

static InvalidationInfo * PrepareInvalidationState ( void  )
static

Definition at line 629 of file inval.c.

630{
631 TransInvalidationInfo *myInfo;
632
634 /* Can't queue transactional message while collecting inplace messages. */
635 Assert(inplaceInvalInfo == NULL);
636
637 if (transInvalInfo != NULL &&
640
641 myInfo = (TransInvalidationInfo *)
643 sizeof(TransInvalidationInfo));
644 myInfo->parent = transInvalInfo;
646
647 /* Now, do we have a previous stack entry? */
648 if (transInvalInfo != NULL)
649 {
650 /* Yes; this one should be for a deeper nesting level. */
652
653 /*
654 * The parent (sub)transaction must not have any current (i.e.,
655 * not-yet-locally-processed) messages. If it did, we'd have a
656 * semantic problem: the new subtransaction presumably ought not be
657 * able to see those events yet, but since the CommandCounter is
658 * linear, that can't work once the subtransaction advances the
659 * counter. This is a convenient place to check for that, as well as
660 * being important to keep management of the message arrays simple.
661 */
663 elog(ERROR, "cannot start a subtransaction when there are unprocessed inval messages");
664
665 /*
666 * MemoryContextAllocZero set firstmsg = nextmsg = 0 in each group,
667 * which is fine for the first (sub)transaction, but otherwise we need
668 * to update them to follow whatever is already in the arrays.
669 */
673 &myInfo->PriorCmdInvalidMsgs);
674 }
675 else
676 {
677 /*
678 * Here, we need only clear any array pointers left over from a prior
679 * transaction.
680 */
685 }
686
687 transInvalInfo = myInfo;
688 return (InvalidationInfo *) myInfo;
689}
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215

References Assert, CatCacheMsgs, InvalidationInfo::CurrentCmdInvalidMsgs, elog, ERROR, GetCurrentTransactionNestLevel(), TransInvalidationInfo::ii, inplaceInvalInfo, InvalMessageArrays, IsTransactionState(), InvalMessageArray::maxmsgs, MemoryContextAllocZero(), InvalMessageArray::msgs, TransInvalidationInfo::my_level, NumMessagesInGroup, TransInvalidationInfo::parent, TransInvalidationInfo::PriorCmdInvalidMsgs, RelCacheMsgs, SetGroupToFollow, TopTransactionContext, and transInvalInfo.

Referenced by CacheInvalidateCatalog(), CacheInvalidateHeapTuple(), CacheInvalidateRelcache(), CacheInvalidateRelcacheAll(), and CacheInvalidateRelcacheByTuple().

◆ ProcessCommittedInvalidationMessages()

void ProcessCommittedInvalidationMessages ( SharedInvalidationMessage msgs,
int  nmsgs,
bool  RelcacheInitFileInval,
Oid  dbid,
Oid  tsid 
)

Definition at line 1062 of file inval.c.

1065{
1066 if (nmsgs <= 0)
1067 return;
1068
1069 elog(DEBUG4, "replaying commit with %d messages%s", nmsgs,
1070 (RelcacheInitFileInval ? " and relcache file invalidation" : ""));
1071
1072 if (RelcacheInitFileInval)
1073 {
1074 elog(DEBUG4, "removing relcache init files for database %u", dbid);
1075
1076 /*
1077 * RelationCacheInitFilePreInvalidate, when the invalidation message
1078 * is for a specific database, requires DatabasePath to be set, but we
1079 * should not use SetDatabasePath during recovery, since it is
1080 * intended to be used only once by normal backends. Hence, a quick
1081 * hack: set DatabasePath directly then unset after use.
1082 */
1083 if (OidIsValid(dbid))
1084 DatabasePath = GetDatabasePath(dbid, tsid);
1085
1087
1088 if (OidIsValid(dbid))
1089 {
1091 DatabasePath = NULL;
1092 }
1093 }
1094
1095 SendSharedInvalidMessages(msgs, nmsgs);
1096
1097 if (RelcacheInitFileInval)
1099}
#define DEBUG4
Definition: elog.h:27
char * DatabasePath
Definition: globals.c:103
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110

References DatabasePath, DEBUG4, elog, GetDatabasePath(), OidIsValid, pfree(), RelationCacheInitFilePostInvalidate(), RelationCacheInitFilePreInvalidate(), and SendSharedInvalidMessages().

Referenced by heap_xlog_inplace(), standby_redo(), and xact_redo_commit().

◆ ProcessInvalidationMessages()

static void ProcessInvalidationMessages ( InvalidationMsgsGroup group,
void(*)(SharedInvalidationMessage *msg)  func 
)
static

Definition at line 532 of file inval.c.

534{
535 ProcessMessageSubGroup(group, CatCacheMsgs, func(msg));
536 ProcessMessageSubGroup(group, RelCacheMsgs, func(msg));
537}

References CatCacheMsgs, ProcessMessageSubGroup, and RelCacheMsgs.

Referenced by AtEOSubXact_Inval(), AtEOXact_Inval(), and CommandEndInvalidationMessages().

◆ ProcessInvalidationMessagesMulti()

static void ProcessInvalidationMessagesMulti ( InvalidationMsgsGroup group,
void(*)(const SharedInvalidationMessage *msgs, int n)  func 
)
static

Definition at line 544 of file inval.c.

546{
547 ProcessMessageSubGroupMulti(group, CatCacheMsgs, func(msgs, n));
548 ProcessMessageSubGroupMulti(group, RelCacheMsgs, func(msgs, n));
549}

References CatCacheMsgs, ProcessMessageSubGroupMulti, and RelCacheMsgs.

Referenced by AtEOXact_Inval(), and AtInplace_Inval().

◆ RegisterCatalogInvalidation()

static void RegisterCatalogInvalidation ( InvalidationInfo info,
Oid  dbId,
Oid  catId 
)
static

Definition at line 579 of file inval.c.

580{
582}
static void AddCatalogInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid catId)
Definition: inval.c:441

References AddCatalogInvalidationMessage(), and InvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateCatalog().

◆ RegisterCatcacheInvalidation()

static void RegisterCatcacheInvalidation ( int  cacheId,
uint32  hashValue,
Oid  dbId,
void *  context 
)
static

Definition at line 562 of file inval.c.

566{
567 InvalidationInfo *info = (InvalidationInfo *) context;
568
570 cacheId, hashValue, dbId);
571}
static void AddCatcacheInvalidationMessage(InvalidationMsgsGroup *group, int id, uint32 hashValue, Oid dbId)
Definition: inval.c:413

References AddCatcacheInvalidationMessage(), and InvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateHeapTupleCommon().

◆ RegisterRelcacheInvalidation()

static void RegisterRelcacheInvalidation ( InvalidationInfo info,
Oid  dbId,
Oid  relId 
)
static

Definition at line 590 of file inval.c.

591{
593
594 /*
595 * Most of the time, relcache invalidation is associated with system
596 * catalog updates, but there are a few cases where it isn't. Quick hack
597 * to ensure that the next CommandCounterIncrement() will think that we
598 * need to do CommandEndInvalidationMessages().
599 */
600 (void) GetCurrentCommandId(true);
601
602 /*
603 * If the relation being invalidated is one of those cached in a relcache
604 * init file, mark that we need to zap that file at commit. For simplicity
605 * invalidations for a specific database always invalidate the shared file
606 * as well. Also zap when we are invalidating whole relcache.
607 */
608 if (relId == InvalidOid || RelationIdIsInInitFile(relId))
609 info->RelcacheInitFileInval = true;
610}
static void AddRelcacheInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
Definition: inval.c:459
bool RelationIdIsInInitFile(Oid relationId)
Definition: relcache.c:6740
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:828

References AddRelcacheInvalidationMessage(), InvalidationInfo::CurrentCmdInvalidMsgs, GetCurrentCommandId(), InvalidOid, RelationIdIsInInitFile(), and InvalidationInfo::RelcacheInitFileInval.

Referenced by CacheInvalidateHeapTupleCommon(), CacheInvalidateRelcache(), CacheInvalidateRelcacheAll(), and CacheInvalidateRelcacheByTuple().

◆ RegisterSnapshotInvalidation()

static void RegisterSnapshotInvalidation ( InvalidationInfo info,
Oid  dbId,
Oid  relId 
)
static

Definition at line 619 of file inval.c.

620{
622}
static void AddSnapshotInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
Definition: inval.c:491

References AddSnapshotInvalidationMessage(), and InvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateHeapTupleCommon().

◆ xactGetCommittedInvalidationMessages()

int xactGetCommittedInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool *  RelcacheInitFileInval 
)

Definition at line 939 of file inval.c.

941{
943 int nummsgs;
944 int nmsgs;
945
946 /* Quick exit if we haven't done anything with invalidation messages. */
947 if (transInvalInfo == NULL)
948 {
949 *RelcacheInitFileInval = false;
950 *msgs = NULL;
951 return 0;
952 }
953
954 /* Must be at top of stack */
956
957 /*
958 * Relcache init file invalidation requires processing both before and
959 * after we send the SI messages. However, we need not do anything unless
960 * we committed.
961 */
962 *RelcacheInitFileInval = transInvalInfo->ii.RelcacheInitFileInval;
963
964 /*
965 * Collect all the pending messages into a single contiguous array of
966 * invalidation messages, to simplify what needs to happen while building
967 * the commit WAL message. Maintain the order that they would be
968 * processed in by AtEOXact_Inval(), to ensure emulated behaviour in redo
969 * is as similar as possible to original. We want the same bugs, if any,
970 * not new ones.
971 */
974
975 *msgs = msgarray = (SharedInvalidationMessage *)
977 nummsgs * sizeof(SharedInvalidationMessage));
978
979 nmsgs = 0;
982 (memcpy(msgarray + nmsgs,
983 msgs,
984 n * sizeof(SharedInvalidationMessage)),
985 nmsgs += n));
988 (memcpy(msgarray + nmsgs,
989 msgs,
990 n * sizeof(SharedInvalidationMessage)),
991 nmsgs += n));
994 (memcpy(msgarray + nmsgs,
995 msgs,
996 n * sizeof(SharedInvalidationMessage)),
997 nmsgs += n));
1000 (memcpy(msgarray + nmsgs,
1001 msgs,
1002 n * sizeof(SharedInvalidationMessage)),
1003 nmsgs += n));
1004 Assert(nmsgs == nummsgs);
1005
1006 return nmsgs;
1007}
MemoryContext CurTransactionContext
Definition: mcxt.c:155

References Assert, CatCacheMsgs, InvalidationInfo::CurrentCmdInvalidMsgs, CurTransactionContext, TransInvalidationInfo::ii, MemoryContextAlloc(), TransInvalidationInfo::my_level, NumMessagesInGroup, TransInvalidationInfo::parent, TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessMessageSubGroupMulti, InvalidationInfo::RelcacheInitFileInval, RelCacheMsgs, and transInvalInfo.

Referenced by RecordTransactionCommit(), and StartPrepare().

Variable Documentation

◆ debug_discard_caches

int debug_discard_caches = 0

Definition at line 258 of file inval.c.

Referenced by AcceptInvalidationMessages(), LookupOpclassInfo(), and RelationBuildDesc().

◆ inplaceInvalInfo

◆ InvalMessageArrays

InvalMessageArray InvalMessageArrays[2]
static

◆ relcache_callback_count

int relcache_callback_count = 0
static

◆ relcache_callback_list

◆ syscache_callback_count

int syscache_callback_count = 0
static

Definition at line 283 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and InvalidateSystemCachesExtended().

◆ syscache_callback_links

int16 syscache_callback_links[SysCacheSize]
static

Definition at line 281 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and CallSyscacheCallbacks().

◆ syscache_callback_list

◆ transInvalInfo