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 "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  InvalidationChunk
 
struct  InvalidationListHeader
 
struct  TransInvalidationInfo
 
struct  SYSCACHECALLBACK
 
struct  RELCACHECALLBACK
 

Macros

#define MAX_SYSCACHE_CALLBACKS   64
 
#define MAX_RELCACHE_CALLBACKS   10
 
#define FIRSTCHUNKSIZE   32
 
#define ProcessMessageList(listHdr, codeFragment)
 
#define ProcessMessageListMulti(listHdr, codeFragment)
 

Typedefs

typedef struct InvalidationChunk InvalidationChunk
 
typedef struct InvalidationListHeader InvalidationListHeader
 
typedef struct TransInvalidationInfo TransInvalidationInfo
 

Functions

static void AddInvalidationMessage (InvalidationChunk **listHdr, SharedInvalidationMessage *msg)
 
static void AppendInvalidationMessageList (InvalidationChunk **destHdr, InvalidationChunk **srcHdr)
 
static void AddCatcacheInvalidationMessage (InvalidationListHeader *hdr, int id, uint32 hashValue, Oid dbId)
 
static void AddCatalogInvalidationMessage (InvalidationListHeader *hdr, Oid dbId, Oid catId)
 
static void AddRelcacheInvalidationMessage (InvalidationListHeader *hdr, Oid dbId, Oid relId)
 
static void AddSnapshotInvalidationMessage (InvalidationListHeader *hdr, Oid dbId, Oid relId)
 
static void AppendInvalidationMessages (InvalidationListHeader *dest, InvalidationListHeader *src)
 
static void ProcessInvalidationMessages (InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
 
static void ProcessInvalidationMessagesMulti (InvalidationListHeader *hdr, void(*func)(const SharedInvalidationMessage *msgs, int n))
 
static void RegisterCatcacheInvalidation (int cacheId, uint32 hashValue, Oid dbId)
 
static void RegisterCatalogInvalidation (Oid dbId, Oid catId)
 
static void RegisterRelcacheInvalidation (Oid dbId, Oid relId)
 
static void RegisterSnapshotInvalidation (Oid dbId, Oid relId)
 
void LocalExecuteInvalidationMessage (SharedInvalidationMessage *msg)
 
void InvalidateSystemCaches (void)
 
void AcceptInvalidationMessages (void)
 
static void PrepareInvalidationState (void)
 
void PostPrepare_Inval (void)
 
static void MakeSharedInvalidMessagesArray (const SharedInvalidationMessage *msgs, int n)
 
int xactGetCommittedInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
void ProcessCommittedInvalidationMessages (SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
 
void AtEOXact_Inval (bool isCommit)
 
void AtEOSubXact_Inval (bool isCommit)
 
void CommandEndInvalidationMessages (void)
 
void CacheInvalidateHeapTuple (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 (RelFileNodeBackend rnode)
 
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 ()
 

Variables

static TransInvalidationInfotransInvalInfo = NULL
 
static SharedInvalidationMessageSharedInvalidMessagesArray
 
static int numSharedInvalidMessagesArray
 
static int maxSharedInvalidMessagesArray
 
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

◆ FIRSTCHUNKSIZE

#define FIRSTCHUNKSIZE   32

◆ MAX_RELCACHE_CALLBACKS

#define MAX_RELCACHE_CALLBACKS   10

Definition at line 194 of file inval.c.

Referenced by CacheRegisterRelcacheCallback().

◆ MAX_SYSCACHE_CALLBACKS

#define MAX_SYSCACHE_CALLBACKS   64

Definition at line 193 of file inval.c.

Referenced by CacheRegisterSyscacheCallback().

◆ ProcessMessageList

#define ProcessMessageList (   listHdr,
  codeFragment 
)
Value:
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 298 of file inval.c.

Referenced by AddRelcacheInvalidationMessage(), AddSnapshotInvalidationMessage(), and ProcessInvalidationMessages().

◆ ProcessMessageListMulti

#define ProcessMessageListMulti (   listHdr,
  codeFragment 
)
Value:
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 318 of file inval.c.

Referenced by ProcessInvalidationMessagesMulti().

Typedef Documentation

◆ InvalidationChunk

◆ InvalidationListHeader

◆ TransInvalidationInfo

Function Documentation

◆ AcceptInvalidationMessages()

void AcceptInvalidationMessages ( void  )

Definition at line 684 of file inval.c.

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

Referenced by apply_handle_commit(), AtStart_Cache(), ConditionalLockRelation(), ConditionalLockRelationOid(), delay_execution_planner(), InitializeSessionUserId(), LockDatabaseObject(), LockRelation(), LockRelationOid(), LockSharedObject(), LogicalRepApplyLoop(), ProcessCatchupInterrupt(), RangeVarGetRelidExtended(), relation_openrv(), relation_openrv_extended(), RemoveRelations(), and write_relcache_init_file().

685 {
688 
689  /*
690  * Test code to force cache flushes anytime a flush could happen.
691  *
692  * If used with CLOBBER_FREED_MEMORY, CLOBBER_CACHE_ALWAYS provides a
693  * fairly thorough test that the system contains no cache-flush hazards.
694  * However, it also makes the system unbelievably slow --- the regression
695  * tests take about 100 times longer than normal.
696  *
697  * If you're a glutton for punishment, try CLOBBER_CACHE_RECURSIVELY. This
698  * slows things by at least a factor of 10000, so I wouldn't suggest
699  * trying to run the entire regression tests that way. It's useful to try
700  * a few simple tests, to make sure that cache reload isn't subject to
701  * internal cache-flush hazards, but after you've done a few thousand
702  * recursive reloads it's unlikely you'll learn more.
703  */
704 #if defined(CLOBBER_CACHE_ALWAYS)
705  {
706  static bool in_recursion = false;
707 
708  if (!in_recursion)
709  {
710  in_recursion = true;
712  in_recursion = false;
713  }
714  }
715 #elif defined(CLOBBER_CACHE_RECURSIVELY)
716  {
717  static int recursion_depth = 0;
718 
719  /* Maximum depth is arbitrary depending on your threshold of pain */
720  if (recursion_depth < 3)
721  {
722  recursion_depth++;
724  recursion_depth--;
725  }
726  }
727 #endif
728 }
static int recursion_depth
Definition: elog.c:148
void InvalidateSystemCaches(void)
Definition: inval.c:646
void ReceiveSharedInvalidMessages(void(*invalFunction)(SharedInvalidationMessage *msg), void(*resetFunction)(void))
Definition: sinval.c:71
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:559

◆ AddCatalogInvalidationMessage()

static void AddCatalogInvalidationMessage ( InvalidationListHeader hdr,
Oid  dbId,
Oid  catId 
)
static

Definition at line 370 of file inval.c.

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

Referenced by RegisterCatalogInvalidation().

372 {
374 
376  msg.cat.dbId = dbId;
377  msg.cat.catId = catId;
378  /* check AddCatcacheInvalidationMessage() for an explanation */
379  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
380 
381  AddInvalidationMessage(&hdr->cclist, &msg);
382 }
static void AddInvalidationMessage(InvalidationChunk **listHdr, SharedInvalidationMessage *msg)
Definition: inval.c:232
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
InvalidationChunk * cclist
Definition: inval.c:137
SharedInvalCatalogMsg cat
Definition: sinval.h:117
#define SHAREDINVALCATALOG_ID
Definition: sinval.h:67

◆ AddCatcacheInvalidationMessage()

static void AddCatcacheInvalidationMessage ( InvalidationListHeader hdr,
int  id,
uint32  hashValue,
Oid  dbId 
)
static

Definition at line 342 of file inval.c.

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

Referenced by RegisterCatcacheInvalidation().

344 {
346 
347  Assert(id < CHAR_MAX);
348  msg.cc.id = (int8) id;
349  msg.cc.dbId = dbId;
350  msg.cc.hashValue = hashValue;
351 
352  /*
353  * Define padding bytes in SharedInvalidationMessage structs to be
354  * defined. Otherwise the sinvaladt.c ringbuffer, which is accessed by
355  * multiple processes, will cause spurious valgrind warnings about
356  * undefined memory being used. That's because valgrind remembers the
357  * undefined bytes from the last local process's store, not realizing that
358  * another process has written since, filling the previously uninitialized
359  * bytes
360  */
361  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
362 
363  AddInvalidationMessage(&hdr->cclist, &msg);
364 }
static void AddInvalidationMessage(InvalidationChunk **listHdr, SharedInvalidationMessage *msg)
Definition: inval.c:232
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
InvalidationChunk * cclist
Definition: inval.c:137
SharedInvalCatcacheMsg cc
Definition: sinval.h:116
signed char int8
Definition: c.h:360
#define Assert(condition)
Definition: c.h:745

◆ AddInvalidationMessage()

static void AddInvalidationMessage ( InvalidationChunk **  listHdr,
SharedInvalidationMessage msg 
)
static

Definition at line 232 of file inval.c.

References CurTransactionContext, FIRSTCHUNKSIZE, InvalidationChunk::maxitems, MemoryContextAlloc(), InvalidationChunk::msgs, InvalidationChunk::next, InvalidationChunk::nitems, and offsetof.

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

234 {
235  InvalidationChunk *chunk = *listHdr;
236 
237  if (chunk == NULL)
238  {
239  /* First time through; create initial chunk */
240 #define FIRSTCHUNKSIZE 32
241  chunk = (InvalidationChunk *)
243  offsetof(InvalidationChunk, msgs) +
245  chunk->nitems = 0;
246  chunk->maxitems = FIRSTCHUNKSIZE;
247  chunk->next = *listHdr;
248  *listHdr = chunk;
249  }
250  else if (chunk->nitems >= chunk->maxitems)
251  {
252  /* Need another chunk; double size of last chunk */
253  int chunksize = 2 * chunk->maxitems;
254 
255  chunk = (InvalidationChunk *)
257  offsetof(InvalidationChunk, msgs) +
258  chunksize * sizeof(SharedInvalidationMessage));
259  chunk->nitems = 0;
260  chunk->maxitems = chunksize;
261  chunk->next = *listHdr;
262  *listHdr = chunk;
263  }
264  /* Okay, add message to current chunk */
265  chunk->msgs[chunk->nitems] = *msg;
266  chunk->nitems++;
267 }
#define FIRSTCHUNKSIZE
SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER]
Definition: inval.c:132
MemoryContext CurTransactionContext
Definition: mcxt.c:50
struct InvalidationChunk * next
Definition: inval.c:129
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define offsetof(type, field)
Definition: c.h:668

◆ AddRelcacheInvalidationMessage()

static void AddRelcacheInvalidationMessage ( InvalidationListHeader hdr,
Oid  dbId,
Oid  relId 
)
static

Definition at line 388 of file inval.c.

References AddInvalidationMessage(), SharedInvalRelcacheMsg::dbId, SharedInvalRelcacheMsg::id, InvalidOid, ProcessMessageList, SharedInvalidationMessage::rc, InvalidationListHeader::rclist, SharedInvalRelcacheMsg::relId, SHAREDINVALRELCACHE_ID, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by RegisterRelcacheInvalidation().

390 {
392 
393  /*
394  * Don't add a duplicate item. We assume dbId need not be checked because
395  * it will never change. InvalidOid for relId means all relations so we
396  * don't need to add individual ones when it is present.
397  */
399  if (msg->rc.id == SHAREDINVALRELCACHE_ID &&
400  (msg->rc.relId == relId ||
401  msg->rc.relId == InvalidOid))
402  return);
403 
404  /* OK, add the item */
406  msg.rc.dbId = dbId;
407  msg.rc.relId = relId;
408  /* check AddCatcacheInvalidationMessage() for an explanation */
409  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
410 
411  AddInvalidationMessage(&hdr->rclist, &msg);
412 }
static void AddInvalidationMessage(InvalidationChunk **listHdr, SharedInvalidationMessage *msg)
Definition: inval.c:232
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
SharedInvalRelcacheMsg rc
Definition: sinval.h:118
#define ProcessMessageList(listHdr, codeFragment)
Definition: inval.c:298
#define SHAREDINVALRELCACHE_ID
Definition: sinval.h:76
#define InvalidOid
Definition: postgres_ext.h:36
InvalidationChunk * rclist
Definition: inval.c:138

◆ AddSnapshotInvalidationMessage()

static void AddSnapshotInvalidationMessage ( InvalidationListHeader hdr,
Oid  dbId,
Oid  relId 
)
static

Definition at line 418 of file inval.c.

References AddInvalidationMessage(), SharedInvalSnapshotMsg::dbId, SharedInvalSnapshotMsg::id, ProcessMessageList, InvalidationListHeader::rclist, SharedInvalSnapshotMsg::relId, SHAREDINVALSNAPSHOT_ID, SharedInvalidationMessage::sn, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by RegisterSnapshotInvalidation().

420 {
422 
423  /* Don't add a duplicate item */
424  /* We assume dbId need not be checked because it will never change */
426  if (msg->sn.id == SHAREDINVALSNAPSHOT_ID &&
427  msg->sn.relId == relId)
428  return);
429 
430  /* OK, add the item */
432  msg.sn.dbId = dbId;
433  msg.sn.relId = relId;
434  /* check AddCatcacheInvalidationMessage() for an explanation */
435  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
436 
437  AddInvalidationMessage(&hdr->rclist, &msg);
438 }
SharedInvalSnapshotMsg sn
Definition: sinval.h:121
static void AddInvalidationMessage(InvalidationChunk **listHdr, SharedInvalidationMessage *msg)
Definition: inval.c:232
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
#define ProcessMessageList(listHdr, codeFragment)
Definition: inval.c:298
#define SHAREDINVALSNAPSHOT_ID
Definition: sinval.h:104
InvalidationChunk * rclist
Definition: inval.c:138

◆ AppendInvalidationMessageList()

static void AppendInvalidationMessageList ( InvalidationChunk **  destHdr,
InvalidationChunk **  srcHdr 
)
static

Definition at line 274 of file inval.c.

References InvalidationChunk::next.

Referenced by AppendInvalidationMessages().

276 {
277  InvalidationChunk *chunk = *srcHdr;
278 
279  if (chunk == NULL)
280  return; /* nothing to do */
281 
282  while (chunk->next != NULL)
283  chunk = chunk->next;
284 
285  chunk->next = *destHdr;
286 
287  *destHdr = *srcHdr;
288 
289  *srcHdr = NULL;
290 }
struct InvalidationChunk * next
Definition: inval.c:129

◆ AppendInvalidationMessages()

static void AppendInvalidationMessages ( InvalidationListHeader dest,
InvalidationListHeader src 
)
static

Definition at line 445 of file inval.c.

References AppendInvalidationMessageList(), InvalidationListHeader::cclist, and InvalidationListHeader::rclist.

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

447 {
450 }
InvalidationChunk * cclist
Definition: inval.c:137
InvalidationChunk * rclist
Definition: inval.c:138
static void AppendInvalidationMessageList(InvalidationChunk **destHdr, InvalidationChunk **srcHdr)
Definition: inval.c:274

◆ AtEOSubXact_Inval()

void AtEOSubXact_Inval ( bool  isCommit)

Definition at line 1011 of file inval.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

1012 {
1013  int my_level;
1015 
1016  /* Quick exit if no messages. */
1017  if (myInfo == NULL)
1018  return;
1019 
1020  /* Also bail out quickly if messages are not for this level. */
1021  my_level = GetCurrentTransactionNestLevel();
1022  if (myInfo->my_level != my_level)
1023  {
1024  Assert(myInfo->my_level < my_level);
1025  return;
1026  }
1027 
1028  if (isCommit)
1029  {
1030  /* If CurrentCmdInvalidMsgs still has anything, fix it */
1032 
1033  /*
1034  * We create invalidation stack entries lazily, so the parent might
1035  * not have one. Instead of creating one, moving all the data over,
1036  * and then freeing our own, we can just adjust the level of our own
1037  * entry.
1038  */
1039  if (myInfo->parent == NULL || myInfo->parent->my_level < my_level - 1)
1040  {
1041  myInfo->my_level--;
1042  return;
1043  }
1044 
1045  /* Pass up my inval messages to parent */
1047  &myInfo->PriorCmdInvalidMsgs);
1048 
1049  /* Pending relcache inval becomes parent's problem too */
1050  if (myInfo->RelcacheInitFileInval)
1051  myInfo->parent->RelcacheInitFileInval = true;
1052 
1053  /* Pop the transaction state stack */
1054  transInvalInfo = myInfo->parent;
1055 
1056  /* Need not free anything else explicitly */
1057  pfree(myInfo);
1058  }
1059  else
1060  {
1063 
1064  /* Pop the transaction state stack */
1065  transInvalInfo = myInfo->parent;
1066 
1067  /* Need not free anything else explicitly */
1068  pfree(myInfo);
1069  }
1070 }
static void AppendInvalidationMessages(InvalidationListHeader *dest, InvalidationListHeader *src)
Definition: inval.c:445
InvalidationListHeader PriorCmdInvalidMsgs
Definition: inval.c:170
void CommandEndInvalidationMessages(void)
Definition: inval.c:1088
struct TransInvalidationInfo * parent
Definition: inval.c:161
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
void pfree(void *pointer)
Definition: mcxt.c:1057
bool RelcacheInitFileInval
Definition: inval.c:173
static void ProcessInvalidationMessages(InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:459
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:857
#define Assert(condition)
Definition: c.h:745
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:559

◆ AtEOXact_Inval()

void AtEOXact_Inval ( bool  isCommit)

Definition at line 952 of file inval.c.

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

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

953 {
954  /* Quick exit if no messages */
955  if (transInvalInfo == NULL)
956  return;
957 
958  /* Must be at top of stack */
960 
961  if (isCommit)
962  {
963  /*
964  * Relcache init file invalidation requires processing both before and
965  * after we send the SI messages. However, we need not do anything
966  * unless we committed.
967  */
970 
973 
976 
979  }
980  else
981  {
984  }
985 
986  /* Need not free anything explicitly */
987  transInvalInfo = NULL;
990 }
static void AppendInvalidationMessages(InvalidationListHeader *dest, InvalidationListHeader *src)
Definition: inval.c:445
static SharedInvalidationMessage * SharedInvalidMessagesArray
Definition: inval.c:178
InvalidationListHeader PriorCmdInvalidMsgs
Definition: inval.c:170
struct TransInvalidationInfo * parent
Definition: inval.c:161
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
static int numSharedInvalidMessagesArray
Definition: inval.c:179
static void ProcessInvalidationMessagesMulti(InvalidationListHeader *hdr, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:471
bool RelcacheInitFileInval
Definition: inval.c:173
static void ProcessInvalidationMessages(InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:459
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6323
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:6298
#define Assert(condition)
Definition: c.h:745
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:559

◆ CacheInvalidateCatalog()

void CacheInvalidateCatalog ( Oid  catalogId)

Definition at line 1254 of file inval.c.

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

Referenced by finish_heap_swap().

1255 {
1256  Oid databaseId;
1257 
1259 
1260  if (IsSharedRelation(catalogId))
1261  databaseId = InvalidOid;
1262  else
1263  databaseId = MyDatabaseId;
1264 
1265  RegisterCatalogInvalidation(databaseId, catalogId);
1266 }
unsigned int Oid
Definition: postgres_ext.h:31
static void PrepareInvalidationState(void)
Definition: inval.c:735
Oid MyDatabaseId
Definition: globals.c:85
static void RegisterCatalogInvalidation(Oid dbId, Oid catId)
Definition: inval.c:503
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:238
#define InvalidOid
Definition: postgres_ext.h:36

◆ CacheInvalidateHeapTuple()

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

Definition at line 1122 of file inval.c.

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

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

1125 {
1126  Oid tupleRelId;
1127  Oid databaseId;
1128  Oid relationId;
1129 
1130  /* Do nothing during bootstrap */
1132  return;
1133 
1134  /*
1135  * We only need to worry about invalidation for tuples that are in system
1136  * catalogs; user-relation tuples are never in catcaches and can't affect
1137  * the relcache either.
1138  */
1139  if (!IsCatalogRelation(relation))
1140  return;
1141 
1142  /*
1143  * IsCatalogRelation() will return true for TOAST tables of system
1144  * catalogs, but we don't care about those, either.
1145  */
1146  if (IsToastRelation(relation))
1147  return;
1148 
1149  /*
1150  * If we're not prepared to queue invalidation messages for this
1151  * subtransaction level, get ready now.
1152  */
1154 
1155  /*
1156  * First let the catcache do its thing
1157  */
1158  tupleRelId = RelationGetRelid(relation);
1159  if (RelationInvalidatesSnapshotsOnly(tupleRelId))
1160  {
1161  databaseId = IsSharedRelation(tupleRelId) ? InvalidOid : MyDatabaseId;
1162  RegisterSnapshotInvalidation(databaseId, tupleRelId);
1163  }
1164  else
1165  PrepareToInvalidateCacheTuple(relation, tuple, newtuple,
1167 
1168  /*
1169  * Now, is this tuple one of the primary definers of a relcache entry? See
1170  * comments in file header for deeper explanation.
1171  *
1172  * Note we ignore newtuple here; we assume an update cannot move a tuple
1173  * from being part of one relcache entry to being part of another.
1174  */
1175  if (tupleRelId == RelationRelationId)
1176  {
1177  Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple);
1178 
1179  relationId = classtup->oid;
1180  if (classtup->relisshared)
1181  databaseId = InvalidOid;
1182  else
1183  databaseId = MyDatabaseId;
1184  }
1185  else if (tupleRelId == AttributeRelationId)
1186  {
1187  Form_pg_attribute atttup = (Form_pg_attribute) GETSTRUCT(tuple);
1188 
1189  relationId = atttup->attrelid;
1190 
1191  /*
1192  * KLUGE ALERT: we always send the relcache event with MyDatabaseId,
1193  * even if the rel in question is shared (which we can't easily tell).
1194  * This essentially means that only backends in this same database
1195  * will react to the relcache flush request. This is in fact
1196  * appropriate, since only those backends could see our pg_attribute
1197  * change anyway. It looks a bit ugly though. (In practice, shared
1198  * relations can't have schema changes after bootstrap, so we should
1199  * never come here for a shared rel anyway.)
1200  */
1201  databaseId = MyDatabaseId;
1202  }
1203  else if (tupleRelId == IndexRelationId)
1204  {
1205  Form_pg_index indextup = (Form_pg_index) GETSTRUCT(tuple);
1206 
1207  /*
1208  * When a pg_index row is updated, we should send out a relcache inval
1209  * for the index relation. As above, we don't know the shared status
1210  * of the index, but in practice it doesn't matter since indexes of
1211  * shared catalogs can't have such updates.
1212  */
1213  relationId = indextup->indexrelid;
1214  databaseId = MyDatabaseId;
1215  }
1216  else if (tupleRelId == ConstraintRelationId)
1217  {
1218  Form_pg_constraint constrtup = (Form_pg_constraint) GETSTRUCT(tuple);
1219 
1220  /*
1221  * Foreign keys are part of relcache entries, too, so send out an
1222  * inval for the table that the FK applies to.
1223  */
1224  if (constrtup->contype == CONSTRAINT_FOREIGN &&
1225  OidIsValid(constrtup->conrelid))
1226  {
1227  relationId = constrtup->conrelid;
1228  databaseId = MyDatabaseId;
1229  }
1230  else
1231  return;
1232  }
1233  else
1234  return;
1235 
1236  /*
1237  * Yes. We need to register a relcache invalidation event.
1238  */
1239  RegisterRelcacheInvalidation(databaseId, relationId);
1240 }
bool IsToastRelation(Relation relation)
Definition: catalog.c:140
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:98
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
Definition: catcache.c:2007
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
static void PrepareInvalidationState(void)
Definition: inval.c:735
FormData_pg_index * Form_pg_index
Definition: pg_index.h:68
Oid MyDatabaseId
Definition: globals.c:85
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:238
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:515
FormData_pg_constraint * Form_pg_constraint
static void RegisterCatcacheInvalidation(int cacheId, uint32 hashValue, Oid dbId)
Definition: inval.c:489
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1473
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:393
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define RelationGetRelid(relation)
Definition: rel.h:456
static void RegisterSnapshotInvalidation(Oid dbId, Oid relId)
Definition: inval.c:545

◆ CacheInvalidateRelcache()

void CacheInvalidateRelcache ( Relation  relation)

Definition at line 1278 of file inval.c.

References InvalidOid, MyDatabaseId, PrepareInvalidationState(), RelationData::rd_rel, RegisterRelcacheInvalidation(), and RelationGetRelid.

Referenced by AlterPolicy(), ATExecAlterConstraint(), ATExecDetachPartition(), ATExecGenericOptions(), ATExecValidateConstraint(), CreatePolicy(), CreateStatistics(), EnableDisableRule(), EnableDisableTrigger(), index_concurrently_set_dead(), index_create(), index_drop(), publication_add_relation(), reindex_index(), RelationSetNewRelfilenode(), RemovePolicyById(), RemoveRewriteRuleById(), RemoveRoleFromObjectPolicy(), RemoveTriggerById(), rename_constraint_internal(), rename_policy(), RenameRewriteRule(), renametrig(), SetRelationNumChecks(), StorePartitionBound(), and StorePartitionKey().

1279 {
1280  Oid databaseId;
1281  Oid relationId;
1282 
1284 
1285  relationId = RelationGetRelid(relation);
1286  if (relation->rd_rel->relisshared)
1287  databaseId = InvalidOid;
1288  else
1289  databaseId = MyDatabaseId;
1290 
1291  RegisterRelcacheInvalidation(databaseId, relationId);
1292 }
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
static void PrepareInvalidationState(void)
Definition: inval.c:735
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:515
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ CacheInvalidateRelcacheAll()

void CacheInvalidateRelcacheAll ( void  )

Definition at line 1302 of file inval.c.

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

Referenced by AlterPublicationOptions().

1303 {
1305 
1307 }
static void PrepareInvalidationState(void)
Definition: inval.c:735
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:515

◆ CacheInvalidateRelcacheByRelid()

void CacheInvalidateRelcacheByRelid ( Oid  relid)

Definition at line 1337 of file inval.c.

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

Referenced by AlterPublicationOptions(), ATExecAlterConstraint(), ATExecDetachPartition(), DefineIndex(), heap_drop_with_catalog(), ReindexRelationConcurrently(), RemovePublicationRelById(), RemoveStatisticsById(), and StorePartitionBound().

1338 {
1339  HeapTuple tup;
1340 
1342 
1343  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1344  if (!HeapTupleIsValid(tup))
1345  elog(ERROR, "cache lookup failed for relation %u", relid);
1347  ReleaseSysCache(tup);
1348 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static void PrepareInvalidationState(void)
Definition: inval.c:735
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1314

◆ CacheInvalidateRelcacheByTuple()

void CacheInvalidateRelcacheByTuple ( HeapTuple  classTuple)

Definition at line 1314 of file inval.c.

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

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

1315 {
1316  Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple);
1317  Oid databaseId;
1318  Oid relationId;
1319 
1321 
1322  relationId = classtup->oid;
1323  if (classtup->relisshared)
1324  databaseId = InvalidOid;
1325  else
1326  databaseId = MyDatabaseId;
1327  RegisterRelcacheInvalidation(databaseId, relationId);
1328 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
unsigned int Oid
Definition: postgres_ext.h:31
static void PrepareInvalidationState(void)
Definition: inval.c:735
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:515
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153

◆ CacheInvalidateRelmap()

void CacheInvalidateRelmap ( Oid  databaseId)

Definition at line 1407 of file inval.c.

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

Referenced by write_relmap_file().

1408 {
1410 
1411  msg.rm.id = SHAREDINVALRELMAP_ID;
1412  msg.rm.dbId = databaseId;
1413  /* check AddCatcacheInvalidationMessage() for an explanation */
1414  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1415 
1416  SendSharedInvalidMessages(&msg, 1);
1417 }
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
SharedInvalRelmapMsg rm
Definition: sinval.h:120
#define SHAREDINVALRELMAP_ID
Definition: sinval.h:96
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49

◆ CacheInvalidateSmgr()

void CacheInvalidateSmgr ( RelFileNodeBackend  rnode)

Definition at line 1377 of file inval.c.

References RelFileNodeBackend::backend, SharedInvalSmgrMsg::backend_hi, SharedInvalSmgrMsg::backend_lo, SharedInvalSmgrMsg::id, RelFileNodeBackend::node, SharedInvalSmgrMsg::rnode, SendSharedInvalidMessages(), SHAREDINVALSMGR_ID, SharedInvalidationMessage::sm, and VALGRIND_MAKE_MEM_DEFINED.

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

1378 {
1380 
1381  msg.sm.id = SHAREDINVALSMGR_ID;
1382  msg.sm.backend_hi = rnode.backend >> 16;
1383  msg.sm.backend_lo = rnode.backend & 0xffff;
1384  msg.sm.rnode = rnode.node;
1385  /* check AddCatcacheInvalidationMessage() for an explanation */
1386  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1387 
1388  SendSharedInvalidMessages(&msg, 1);
1389 }
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
RelFileNode node
Definition: relfilenode.h:74
SharedInvalSmgrMsg sm
Definition: sinval.h:119
BackendId backend
Definition: relfilenode.h:75
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49
uint16 backend_lo
Definition: sinval.h:92
RelFileNode rnode
Definition: sinval.h:93
#define SHAREDINVALSMGR_ID
Definition: sinval.h:85

◆ CacheRegisterRelcacheCallback()

void CacheRegisterRelcacheCallback ( RelcacheCallbackFunction  func,
Datum  arg 
)

Definition at line 1476 of file inval.c.

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

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

1478 {
1480  elog(FATAL, "out of relcache_callback_list slots");
1481 
1484 
1486 }
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
#define MAX_RELCACHE_CALLBACKS
Definition: inval.c:194
static int relcache_callback_count
Definition: inval.c:214
RelcacheCallbackFunction function
Definition: inval.c:210
#define FATAL
Definition: elog.h:52
#define elog(elevel,...)
Definition: elog.h:214
void * arg

◆ CacheRegisterSyscacheCallback()

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

Definition at line 1434 of file inval.c.

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

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

1437 {
1438  if (cacheid < 0 || cacheid >= SysCacheSize)
1439  elog(FATAL, "invalid cache ID: %d", cacheid);
1441  elog(FATAL, "out of syscache_callback_list slots");
1442 
1443  if (syscache_callback_links[cacheid] == 0)
1444  {
1445  /* first callback for this cache */
1447  }
1448  else
1449  {
1450  /* add to end of chain, so that older callbacks are called first */
1451  int i = syscache_callback_links[cacheid] - 1;
1452 
1453  while (syscache_callback_list[i].link > 0)
1454  i = syscache_callback_list[i].link - 1;
1456  }
1457 
1462 
1464 }
int16 link
Definition: inval.c:199
#define SysCacheSize
Definition: syscache.h:113
#define FATAL
Definition: elog.h:52
#define MAX_SYSCACHE_CALLBACKS
Definition: inval.c:193
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
static int syscache_callback_count
Definition: inval.c:206
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:204
#define elog(elevel,...)
Definition: elog.h:214
int i
void * arg
SyscacheCallbackFunction function
Definition: inval.c:200

◆ CallSyscacheCallbacks()

void CallSyscacheCallbacks ( int  cacheid,
uint32  hashvalue 
)

Definition at line 1495 of file inval.c.

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

Referenced by CatalogCacheFlushCatalog(), and LocalExecuteInvalidationMessage().

1496 {
1497  int i;
1498 
1499  if (cacheid < 0 || cacheid >= SysCacheSize)
1500  elog(ERROR, "invalid cache ID: %d", cacheid);
1501 
1502  i = syscache_callback_links[cacheid] - 1;
1503  while (i >= 0)
1504  {
1505  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
1506 
1507  Assert(ccitem->id == cacheid);
1508  ccitem->function(ccitem->arg, cacheid, hashvalue);
1509  i = ccitem->link - 1;
1510  }
1511 }
int16 link
Definition: inval.c:199
#define SysCacheSize
Definition: syscache.h:113
#define ERROR
Definition: elog.h:43
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
#define Assert(condition)
Definition: c.h:745
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:204
#define elog(elevel,...)
Definition: elog.h:214
int i
SyscacheCallbackFunction function
Definition: inval.c:200

◆ CommandEndInvalidationMessages()

void CommandEndInvalidationMessages ( void  )

Definition at line 1088 of file inval.c.

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

Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().

1089 {
1090  /*
1091  * You might think this shouldn't be called outside any transaction, but
1092  * bootstrap does it, and also ABORT issued when not in a transaction. So
1093  * just quietly return if no state to work on.
1094  */
1095  if (transInvalInfo == NULL)
1096  return;
1097 
1100 
1101  /* WAL Log per-command invalidation messages for wal_level=logical */
1102  if (XLogLogicalInfoActive())
1104 
1107 }
static void AppendInvalidationMessages(InvalidationListHeader *dest, InvalidationListHeader *src)
Definition: inval.c:445
InvalidationListHeader PriorCmdInvalidMsgs
Definition: inval.c:170
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
#define XLogLogicalInfoActive()
Definition: xlog.h:208
void LogLogicalInvalidations()
Definition: inval.c:1521
static void ProcessInvalidationMessages(InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:459
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:559

◆ InvalidateSystemCaches()

void InvalidateSystemCaches ( void  )

Definition at line 646 of file inval.c.

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

Referenced by AcceptInvalidationMessages(), ParallelWorkerMain(), pg_logical_replication_slot_advance(), and pg_logical_slot_get_changes_guts().

647 {
648  int i;
649 
652  RelationCacheInvalidate(); /* gets smgr and relmap too */
653 
654  for (i = 0; i < syscache_callback_count; i++)
655  {
656  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
657 
658  ccitem->function(ccitem->arg, ccitem->id, 0);
659  }
660 
661  for (i = 0; i < relcache_callback_count; i++)
662  {
663  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
664 
665  ccitem->function(ccitem->arg, InvalidOid);
666  }
667 }
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
static int relcache_callback_count
Definition: inval.c:214
RelcacheCallbackFunction function
Definition: inval.c:210
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
static int syscache_callback_count
Definition: inval.c:206
#define InvalidOid
Definition: postgres_ext.h:36
void ResetCatalogCaches(void)
Definition: catcache.c:689
void RelationCacheInvalidate(void)
Definition: relcache.c:2831
int i
SyscacheCallbackFunction function
Definition: inval.c:200

◆ LocalExecuteInvalidationMessage()

void LocalExecuteInvalidationMessage ( SharedInvalidationMessage msg)

Definition at line 559 of file inval.c.

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

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

560 {
561  if (msg->id >= 0)
562  {
563  if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
564  {
566 
567  SysCacheInvalidate(msg->cc.id, msg->cc.hashValue);
568 
569  CallSyscacheCallbacks(msg->cc.id, msg->cc.hashValue);
570  }
571  }
572  else if (msg->id == SHAREDINVALCATALOG_ID)
573  {
574  if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
575  {
577 
579 
580  /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
581  }
582  }
583  else if (msg->id == SHAREDINVALRELCACHE_ID)
584  {
585  if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
586  {
587  int i;
588 
589  if (msg->rc.relId == InvalidOid)
591  else
593 
594  for (i = 0; i < relcache_callback_count; i++)
595  {
596  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
597 
598  ccitem->function(ccitem->arg, msg->rc.relId);
599  }
600  }
601  }
602  else if (msg->id == SHAREDINVALSMGR_ID)
603  {
604  /*
605  * We could have smgr entries for relations of other databases, so no
606  * short-circuit test is possible here.
607  */
608  RelFileNodeBackend rnode;
609 
610  rnode.node = msg->sm.rnode;
611  rnode.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
612  smgrclosenode(rnode);
613  }
614  else if (msg->id == SHAREDINVALRELMAP_ID)
615  {
616  /* We only care about our own database and shared catalogs */
617  if (msg->rm.dbId == InvalidOid)
618  RelationMapInvalidate(true);
619  else if (msg->rm.dbId == MyDatabaseId)
620  RelationMapInvalidate(false);
621  }
622  else if (msg->id == SHAREDINVALSNAPSHOT_ID)
623  {
624  /* We only care about our own database and shared catalogs */
625  if (msg->rm.dbId == InvalidOid)
627  else if (msg->rm.dbId == MyDatabaseId)
629  }
630  else
631  elog(FATAL, "unrecognized SI message ID: %d", msg->id);
632 }
SharedInvalRelcacheMsg rc
Definition: sinval.h:118
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
static int relcache_callback_count
Definition: inval.c:214
RelcacheCallbackFunction function
Definition: inval.c:210
void RelationMapInvalidate(bool shared)
Definition: relmapper.c:403
#define FATAL
Definition: elog.h:52
#define SHAREDINVALRELCACHE_ID
Definition: sinval.h:76
SharedInvalRelmapMsg rm
Definition: sinval.h:120
#define SHAREDINVALRELMAP_ID
Definition: sinval.h:96
SharedInvalCatcacheMsg cc
Definition: sinval.h:116
void smgrclosenode(RelFileNodeBackend rnode)
Definition: smgr.c:311
SharedInvalCatalogMsg cat
Definition: sinval.h:117
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1495
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define SHAREDINVALSNAPSHOT_ID
Definition: sinval.h:104
RelFileNode node
Definition: relfilenode.h:74
SharedInvalSmgrMsg sm
Definition: sinval.h:119
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:1449
void CatalogCacheFlushCatalog(Oid catId)
Definition: catcache.c:719
BackendId backend
Definition: relfilenode.h:75
void RelationCacheInvalidateEntry(Oid relationId)
Definition: relcache.c:2788
uint16 backend_lo
Definition: sinval.h:92
#define SHAREDINVALCATALOG_ID
Definition: sinval.h:67
#define elog(elevel,...)
Definition: elog.h:214
void RelationCacheInvalidate(void)
Definition: relcache.c:2831
int i
RelFileNode rnode
Definition: sinval.h:93
#define SHAREDINVALSMGR_ID
Definition: sinval.h:85

◆ LogLogicalInvalidations()

void LogLogicalInvalidations ( void  )

Definition at line 1521 of file inval.c.

References Assert, TransInvalidationInfo::CurrentCmdInvalidMsgs, MakeSharedInvalidMessagesArray(), MinSizeOfXactInvals, xl_xact_invals::nmsgs, numSharedInvalidMessagesArray, pfree(), ProcessInvalidationMessagesMulti(), SharedInvalidMessagesArray, XLOG_XACT_INVALIDATIONS, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by CommandEndInvalidationMessages(), and RecordTransactionCommit().

1522 {
1523  xl_xact_invals xlrec;
1524  SharedInvalidationMessage *invalMessages;
1525  int nmsgs = 0;
1526 
1527  /* Quick exit if we haven't done anything with invalidation messages. */
1528  if (transInvalInfo == NULL)
1529  return;
1530 
1533 
1535  SharedInvalidMessagesArray == NULL));
1536 
1537  invalMessages = SharedInvalidMessagesArray;
1541 
1542  if (nmsgs > 0)
1543  {
1544  /* prepare record */
1545  memset(&xlrec, 0, MinSizeOfXactInvals);
1546  xlrec.nmsgs = nmsgs;
1547 
1548  /* perform insertion */
1549  XLogBeginInsert();
1550  XLogRegisterData((char *) (&xlrec), MinSizeOfXactInvals);
1551  XLogRegisterData((char *) invalMessages,
1552  nmsgs * sizeof(SharedInvalidationMessage));
1553  XLogInsert(RM_XACT_ID, XLOG_XACT_INVALIDATIONS);
1554 
1555  pfree(invalMessages);
1556  }
1557 }
static SharedInvalidationMessage * SharedInvalidMessagesArray
Definition: inval.c:178
#define XLOG_XACT_INVALIDATIONS
Definition: xact.h:153
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
void pfree(void *pointer)
Definition: mcxt.c:1057
static void MakeSharedInvalidMessagesArray(const SharedInvalidationMessage *msgs, int n)
Definition: inval.c:781
static int numSharedInvalidMessagesArray
Definition: inval.c:179
#define MinSizeOfXactInvals
Definition: xact.h:256
static void ProcessInvalidationMessagesMulti(InvalidationListHeader *hdr, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:471
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
#define Assert(condition)
Definition: c.h:745
void XLogBeginInsert(void)
Definition: xloginsert.c:123
int nmsgs
Definition: xact.h:253

◆ MakeSharedInvalidMessagesArray()

static void MakeSharedInvalidMessagesArray ( const SharedInvalidationMessage msgs,
int  n 
)
static

Definition at line 781 of file inval.c.

References FIRSTCHUNKSIZE, maxSharedInvalidMessagesArray, numSharedInvalidMessagesArray, palloc(), and repalloc().

Referenced by LogLogicalInvalidations(), and xactGetCommittedInvalidationMessages().

782 {
783  /*
784  * Initialise array first time through in each commit
785  */
786  if (SharedInvalidMessagesArray == NULL)
787  {
790 
791  /*
792  * Although this is being palloc'd we don't actually free it directly.
793  * We're so close to EOXact that we now we're going to lose it anyhow.
794  */
796  * sizeof(SharedInvalidationMessage));
797  }
798 
800  {
803 
806  * sizeof(SharedInvalidationMessage));
807  }
808 
809  /*
810  * Append the next chunk onto the array
811  */
813  msgs, n * sizeof(SharedInvalidationMessage));
815 }
#define FIRSTCHUNKSIZE
static SharedInvalidationMessage * SharedInvalidMessagesArray
Definition: inval.c:178
static int numSharedInvalidMessagesArray
Definition: inval.c:179
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
static int maxSharedInvalidMessagesArray
Definition: inval.c:180
void * palloc(Size size)
Definition: mcxt.c:950

◆ PostPrepare_Inval()

void PostPrepare_Inval ( void  )

Definition at line 772 of file inval.c.

References AtEOXact_Inval().

Referenced by PrepareTransaction().

773 {
774  AtEOXact_Inval(false);
775 }
void AtEOXact_Inval(bool isCommit)
Definition: inval.c:952

◆ PrepareInvalidationState()

static void PrepareInvalidationState ( void  )
static

Definition at line 735 of file inval.c.

References Assert, GetCurrentTransactionNestLevel(), MemoryContextAllocZero(), TransInvalidationInfo::my_level, TransInvalidationInfo::parent, TopTransactionContext, and transInvalInfo.

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

736 {
737  TransInvalidationInfo *myInfo;
738 
739  if (transInvalInfo != NULL &&
741  return;
742 
743  myInfo = (TransInvalidationInfo *)
745  sizeof(TransInvalidationInfo));
746  myInfo->parent = transInvalInfo;
748 
749  /*
750  * If there's any previous entry, this one should be for a deeper nesting
751  * level.
752  */
753  Assert(transInvalInfo == NULL ||
754  myInfo->my_level > transInvalInfo->my_level);
755 
756  transInvalInfo = myInfo;
757 }
MemoryContext TopTransactionContext
Definition: mcxt.c:49
struct TransInvalidationInfo * parent
Definition: inval.c:161
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:857
#define Assert(condition)
Definition: c.h:745

◆ ProcessCommittedInvalidationMessages()

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

Definition at line 887 of file inval.c.

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

Referenced by standby_redo(), and xact_redo_commit().

890 {
891  if (nmsgs <= 0)
892  return;
893 
894  elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
895  (RelcacheInitFileInval ? " and relcache file invalidation" : ""));
896 
897  if (RelcacheInitFileInval)
898  {
899  elog(trace_recovery(DEBUG4), "removing relcache init files for database %u",
900  dbid);
901 
902  /*
903  * RelationCacheInitFilePreInvalidate, when the invalidation message
904  * is for a specific database, requires DatabasePath to be set, but we
905  * should not use SetDatabasePath during recovery, since it is
906  * intended to be used only once by normal backends. Hence, a quick
907  * hack: set DatabasePath directly then unset after use.
908  */
909  if (OidIsValid(dbid))
910  DatabasePath = GetDatabasePath(dbid, tsid);
911 
913 
914  if (OidIsValid(dbid))
915  {
917  DatabasePath = NULL;
918  }
919  }
920 
921  SendSharedInvalidMessages(msgs, nmsgs);
922 
923  if (RelcacheInitFileInval)
925 }
#define DEBUG4
Definition: elog.h:22
#define OidIsValid(objectId)
Definition: c.h:651
int trace_recovery(int trace_level)
Definition: elog.c:3543
void pfree(void *pointer)
Definition: mcxt.c:1057
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6323
char * DatabasePath
Definition: globals.c:93
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:6298
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49
#define elog(elevel,...)
Definition: elog.h:214

◆ ProcessInvalidationMessages()

static void ProcessInvalidationMessages ( InvalidationListHeader hdr,
void(*)(SharedInvalidationMessage *msg)  func 
)
static

Definition at line 459 of file inval.c.

References InvalidationListHeader::cclist, ProcessMessageList, and InvalidationListHeader::rclist.

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

461 {
462  ProcessMessageList(hdr->cclist, func(msg));
463  ProcessMessageList(hdr->rclist, func(msg));
464 }
#define ProcessMessageList(listHdr, codeFragment)
Definition: inval.c:298
InvalidationChunk * cclist
Definition: inval.c:137
InvalidationChunk * rclist
Definition: inval.c:138

◆ ProcessInvalidationMessagesMulti()

static void ProcessInvalidationMessagesMulti ( InvalidationListHeader hdr,
void(*)(const SharedInvalidationMessage *msgs, int n)  func 
)
static

Definition at line 471 of file inval.c.

References InvalidationListHeader::cclist, ProcessMessageListMulti, and InvalidationListHeader::rclist.

Referenced by AtEOXact_Inval(), LogLogicalInvalidations(), and xactGetCommittedInvalidationMessages().

473 {
474  ProcessMessageListMulti(hdr->cclist, func(msgs, n));
475  ProcessMessageListMulti(hdr->rclist, func(msgs, n));
476 }
#define ProcessMessageListMulti(listHdr, codeFragment)
Definition: inval.c:318
InvalidationChunk * cclist
Definition: inval.c:137
InvalidationChunk * rclist
Definition: inval.c:138

◆ RegisterCatalogInvalidation()

static void RegisterCatalogInvalidation ( Oid  dbId,
Oid  catId 
)
static

Definition at line 503 of file inval.c.

References AddCatalogInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateCatalog().

504 {
506  dbId, catId);
507 }
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
static void AddCatalogInvalidationMessage(InvalidationListHeader *hdr, Oid dbId, Oid catId)
Definition: inval.c:370

◆ RegisterCatcacheInvalidation()

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

Definition at line 489 of file inval.c.

References AddCatcacheInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateHeapTuple().

492 {
494  cacheId, hashValue, dbId);
495 }
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
static void AddCatcacheInvalidationMessage(InvalidationListHeader *hdr, int id, uint32 hashValue, Oid dbId)
Definition: inval.c:342

◆ RegisterRelcacheInvalidation()

static void RegisterRelcacheInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 515 of file inval.c.

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

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

516 {
518  dbId, relId);
519 
520  /*
521  * Most of the time, relcache invalidation is associated with system
522  * catalog updates, but there are a few cases where it isn't. Quick hack
523  * to ensure that the next CommandCounterIncrement() will think that we
524  * need to do CommandEndInvalidationMessages().
525  */
526  (void) GetCurrentCommandId(true);
527 
528  /*
529  * If the relation being invalidated is one of those cached in a relcache
530  * init file, mark that we need to zap that file at commit. For simplicity
531  * invalidations for a specific database always invalidate the shared file
532  * as well. Also zap when we are invalidating whole relcache.
533  */
534  if (relId == InvalidOid || RelationIdIsInInitFile(relId))
536 }
bool RelationIdIsInInitFile(Oid relationId)
Definition: relcache.c:6258
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
bool RelcacheInitFileInval
Definition: inval.c:173
#define InvalidOid
Definition: postgres_ext.h:36
static void AddRelcacheInvalidationMessage(InvalidationListHeader *hdr, Oid dbId, Oid relId)
Definition: inval.c:388
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761

◆ RegisterSnapshotInvalidation()

static void RegisterSnapshotInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 545 of file inval.c.

References AddSnapshotInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateHeapTuple().

546 {
548  dbId, relId);
549 }
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
static void AddSnapshotInvalidationMessage(InvalidationListHeader *hdr, Oid dbId, Oid relId)
Definition: inval.c:418

◆ xactGetCommittedInvalidationMessages()

int xactGetCommittedInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool RelcacheInitFileInval 
)

Definition at line 831 of file inval.c.

References Assert, TransInvalidationInfo::CurrentCmdInvalidMsgs, CurTransactionContext, MakeSharedInvalidMessagesArray(), MemoryContextSwitchTo(), TransInvalidationInfo::my_level, numSharedInvalidMessagesArray, TransInvalidationInfo::parent, TransInvalidationInfo::PriorCmdInvalidMsgs, ProcessInvalidationMessagesMulti(), TransInvalidationInfo::RelcacheInitFileInval, and SharedInvalidMessagesArray.

Referenced by RecordTransactionCommit(), and StartPrepare().

833 {
834  MemoryContext oldcontext;
835 
836  /* Quick exit if we haven't done anything with invalidation messages. */
837  if (transInvalInfo == NULL)
838  {
839  *RelcacheInitFileInval = false;
840  *msgs = NULL;
841  return 0;
842  }
843 
844  /* Must be at top of stack */
846 
847  /*
848  * Relcache init file invalidation requires processing both before and
849  * after we send the SI messages. However, we need not do anything unless
850  * we committed.
851  */
852  *RelcacheInitFileInval = transInvalInfo->RelcacheInitFileInval;
853 
854  /*
855  * Walk through TransInvalidationInfo to collect all the messages into a
856  * single contiguous array of invalidation messages. It must be contiguous
857  * so we can copy directly into WAL message. Maintain the order that they
858  * would be processed in by AtEOXact_Inval(), to ensure emulated behaviour
859  * in redo is as similar as possible to original. We want the same bugs,
860  * if any, not new ones.
861  */
863 
868  MemoryContextSwitchTo(oldcontext);
869 
871  SharedInvalidMessagesArray == NULL));
872 
874 
876 }
static SharedInvalidationMessage * SharedInvalidMessagesArray
Definition: inval.c:178
InvalidationListHeader PriorCmdInvalidMsgs
Definition: inval.c:170
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext CurTransactionContext
Definition: mcxt.c:50
struct TransInvalidationInfo * parent
Definition: inval.c:161
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:176
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:167
static void MakeSharedInvalidMessagesArray(const SharedInvalidationMessage *msgs, int n)
Definition: inval.c:781
static int numSharedInvalidMessagesArray
Definition: inval.c:179
static void ProcessInvalidationMessagesMulti(InvalidationListHeader *hdr, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:471
bool RelcacheInitFileInval
Definition: inval.c:173
#define Assert(condition)
Definition: c.h:745

Variable Documentation

◆ maxSharedInvalidMessagesArray

int maxSharedInvalidMessagesArray
static

Definition at line 180 of file inval.c.

Referenced by MakeSharedInvalidMessagesArray().

◆ numSharedInvalidMessagesArray

int numSharedInvalidMessagesArray
static

◆ relcache_callback_count

int relcache_callback_count = 0
static

◆ relcache_callback_list

◆ SharedInvalidMessagesArray

SharedInvalidationMessage* SharedInvalidMessagesArray
static

Definition at line 178 of file inval.c.

Referenced by LogLogicalInvalidations(), and xactGetCommittedInvalidationMessages().

◆ syscache_callback_count

int syscache_callback_count = 0
static

Definition at line 206 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and InvalidateSystemCaches().

◆ syscache_callback_links

int16 syscache_callback_links[SysCacheSize]
static

Definition at line 204 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and CallSyscacheCallbacks().

◆ syscache_callback_list

◆ transInvalInfo

TransInvalidationInfo* transInvalInfo = NULL
static

Definition at line 176 of file inval.c.

Referenced by AtEOSubXact_Inval(), and PrepareInvalidationState().