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/guc.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  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 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)
 
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 InvalidateSystemCachesExtended (bool debug_discard)
 
void AcceptInvalidationMessages (void)
 
static void PrepareInvalidationState (void)
 
void PostPrepare_Inval (void)
 
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 (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
 
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 162 of file inval.c.

◆ MAX_RELCACHE_CALLBACKS

#define MAX_RELCACHE_CALLBACKS   10

Definition at line 254 of file inval.c.

◆ MAX_SYSCACHE_CALLBACKS

#define MAX_SYSCACHE_CALLBACKS   64

Definition at line 253 of file inval.c.

◆ NumMessagesInGroup

#define NumMessagesInGroup (   group)
Value:
NumMessagesInSubGroup(group, RelCacheMsgs))
#define CatCacheMsgs
Definition: inval.c:162
#define NumMessagesInSubGroup(group, subgroup)
Definition: inval.c:195
#define RelCacheMsgs
Definition: inval.c:163

Definition at line 198 of file inval.c.

◆ NumMessagesInSubGroup

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

Definition at line 195 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:172
SharedInvalidationMessage * msgs
Definition: inval.c:168

Definition at line 355 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 373 of file inval.c.

◆ RelCacheMsgs

#define RelCacheMsgs   1

Definition at line 163 of file inval.c.

◆ SetGroupToFollow

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

Definition at line 189 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 182 of file inval.c.

Typedef Documentation

◆ InvalidationMsgsGroup

◆ InvalMessageArray

◆ TransInvalidationInfo

Function Documentation

◆ AcceptInvalidationMessages()

void AcceptInvalidationMessages ( void  )

Definition at line 746 of file inval.c.

747 {
750 
751  /*----------
752  * Test code to force cache flushes anytime a flush could happen.
753  *
754  * This helps detect intermittent faults caused by code that reads a cache
755  * entry and then performs an action that could invalidate the entry, but
756  * rarely actually does so. This can spot issues that would otherwise
757  * only arise with badly timed concurrent DDL, for example.
758  *
759  * The default debug_discard_caches = 0 does no forced cache flushes.
760  *
761  * If used with CLOBBER_FREED_MEMORY,
762  * debug_discard_caches = 1 (formerly known as CLOBBER_CACHE_ALWAYS)
763  * provides a fairly thorough test that the system contains no cache-flush
764  * hazards. However, it also makes the system unbelievably slow --- the
765  * regression tests take about 100 times longer than normal.
766  *
767  * If you're a glutton for punishment, try
768  * debug_discard_caches = 3 (formerly known as CLOBBER_CACHE_RECURSIVELY).
769  * This slows things by at least a factor of 10000, so I wouldn't suggest
770  * trying to run the entire regression tests that way. It's useful to try
771  * a few simple tests, to make sure that cache reload isn't subject to
772  * internal cache-flush hazards, but after you've done a few thousand
773  * recursive reloads it's unlikely you'll learn more.
774  *----------
775  */
776 #ifdef DISCARD_CACHES_ENABLED
777  {
778  static int recursion_depth = 0;
779 
781  {
782  recursion_depth++;
784  recursion_depth--;
785  }
786  }
787 #endif
788 }
static int recursion_depth
Definition: elog.c:154
void InvalidateSystemCachesExtended(bool debug_discard)
Definition: inval.c:708
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:615
void InvalidateSystemCaches(void)
Definition: inval.c:702
int debug_discard_caches
Definition: inval.c:241
void ReceiveSharedInvalidMessages(void(*invalFunction)(SharedInvalidationMessage *msg), void(*resetFunction)(void))
Definition: sinval.c:71

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

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

◆ AddCatalogInvalidationMessage()

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

Definition at line 424 of file inval.c.

426 {
428 
430  msg.cat.dbId = dbId;
431  msg.cat.catId = catId;
432  /* check AddCatcacheInvalidationMessage() for an explanation */
433  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
434 
435  AddInvalidationMessage(group, CatCacheMsgs, &msg);
436 }
static void AddInvalidationMessage(InvalidationMsgsGroup *group, int subgroup, const SharedInvalidationMessage *msg)
Definition: inval.c:291
#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 396 of file inval.c.

398 {
400 
401  Assert(id < CHAR_MAX);
402  msg.cc.id = (int8) id;
403  msg.cc.dbId = dbId;
404  msg.cc.hashValue = hashValue;
405 
406  /*
407  * Define padding bytes in SharedInvalidationMessage structs to be
408  * defined. Otherwise the sinvaladt.c ringbuffer, which is accessed by
409  * multiple processes, will cause spurious valgrind warnings about
410  * undefined memory being used. That's because valgrind remembers the
411  * undefined bytes from the last local process's store, not realizing that
412  * another process has written since, filling the previously uninitialized
413  * bytes
414  */
415  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
416 
417  AddInvalidationMessage(group, CatCacheMsgs, &msg);
418 }
signed char int8
Definition: c.h:481
Assert(fmt[strlen(fmt) - 1] !='\n')
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 291 of file inval.c.

293 {
294  InvalMessageArray *ima = &InvalMessageArrays[subgroup];
295  int nextindex = group->nextmsg[subgroup];
296 
297  if (nextindex >= ima->maxmsgs)
298  {
299  if (ima->msgs == NULL)
300  {
301  /* Create new storage array in TopTransactionContext */
302  int reqsize = 32; /* arbitrary */
303 
306  reqsize * sizeof(SharedInvalidationMessage));
307  ima->maxmsgs = reqsize;
308  Assert(nextindex == 0);
309  }
310  else
311  {
312  /* Enlarge storage array */
313  int reqsize = 2 * ima->maxmsgs;
314 
316  repalloc(ima->msgs,
317  reqsize * sizeof(SharedInvalidationMessage));
318  ima->maxmsgs = reqsize;
319  }
320  }
321  /* Okay, add message to current group */
322  ima->msgs[nextindex] = *msg;
323  group->nextmsg[subgroup]++;
324 }
MemoryContext TopTransactionContext
Definition: mcxt.c:146
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021

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 442 of file inval.c.

444 {
446 
447  /*
448  * Don't add a duplicate item. We assume dbId need not be checked because
449  * it will never change. InvalidOid for relId means all relations so we
450  * don't need to add individual ones when it is present.
451  */
453  if (msg->rc.id == SHAREDINVALRELCACHE_ID &&
454  (msg->rc.relId == relId ||
455  msg->rc.relId == InvalidOid))
456  return);
457 
458  /* OK, add the item */
460  msg.rc.dbId = dbId;
461  msg.rc.relId = relId;
462  /* check AddCatcacheInvalidationMessage() for an explanation */
463  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
464 
465  AddInvalidationMessage(group, RelCacheMsgs, &msg);
466 }
#define ProcessMessageSubGroup(group, subgroup, codeFragment)
Definition: inval.c:355
#define InvalidOid
Definition: postgres_ext.h:36
#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 474 of file inval.c.

476 {
478 
479  /* Don't add a duplicate item */
480  /* We assume dbId need not be checked because it will never change */
482  if (msg->sn.id == SHAREDINVALSNAPSHOT_ID &&
483  msg->sn.relId == relId)
484  return);
485 
486  /* OK, add the item */
488  msg.sn.dbId = dbId;
489  msg.sn.relId = relId;
490  /* check AddCatcacheInvalidationMessage() for an explanation */
491  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
492 
493  AddInvalidationMessage(group, RelCacheMsgs, &msg);
494 }
#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 501 of file inval.c.

503 {
506 }
static void AppendInvalidationMessageSubGroup(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src, int subgroup)
Definition: inval.c:331

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 331 of file inval.c.

334 {
335  /* Messages must be adjacent in main array */
336  Assert(dest->nextmsg[subgroup] == src->firstmsg[subgroup]);
337 
338  /* ... which makes this easy: */
339  dest->nextmsg[subgroup] = src->nextmsg[subgroup];
340 
341  /*
342  * This is handy for some callers and irrelevant for others. But we do it
343  * always, reasoning that it's bad to leave different groups pointing at
344  * the same fragment of the message array.
345  */
346  SetSubGroupToFollow(src, dest, subgroup);
347 }
#define SetSubGroupToFollow(targetgroup, priorgroup, subgroup)
Definition: inval.c:182

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 1085 of file inval.c.

1086 {
1087  int my_level;
1089 
1090  /* Quick exit if no messages. */
1091  if (myInfo == NULL)
1092  return;
1093 
1094  /* Also bail out quickly if messages are not for this level. */
1095  my_level = GetCurrentTransactionNestLevel();
1096  if (myInfo->my_level != my_level)
1097  {
1098  Assert(myInfo->my_level < my_level);
1099  return;
1100  }
1101 
1102  if (isCommit)
1103  {
1104  /* If CurrentCmdInvalidMsgs still has anything, fix it */
1106 
1107  /*
1108  * We create invalidation stack entries lazily, so the parent might
1109  * not have one. Instead of creating one, moving all the data over,
1110  * and then freeing our own, we can just adjust the level of our own
1111  * entry.
1112  */
1113  if (myInfo->parent == NULL || myInfo->parent->my_level < my_level - 1)
1114  {
1115  myInfo->my_level--;
1116  return;
1117  }
1118 
1119  /*
1120  * Pass up my inval messages to parent. Notice that we stick them in
1121  * PriorCmdInvalidMsgs, not CurrentCmdInvalidMsgs, since they've
1122  * already been locally processed. (This would trigger the Assert in
1123  * AppendInvalidationMessageSubGroup if the parent's
1124  * CurrentCmdInvalidMsgs isn't empty; but we already checked that in
1125  * PrepareInvalidationState.)
1126  */
1128  &myInfo->PriorCmdInvalidMsgs);
1129 
1130  /* Must readjust parent's CurrentCmdInvalidMsgs indexes now */
1132  &myInfo->parent->PriorCmdInvalidMsgs);
1133 
1134  /* Pending relcache inval becomes parent's problem too */
1135  if (myInfo->RelcacheInitFileInval)
1136  myInfo->parent->RelcacheInitFileInval = true;
1137 
1138  /* Pop the transaction state stack */
1139  transInvalInfo = myInfo->parent;
1140 
1141  /* Need not free anything else explicitly */
1142  pfree(myInfo);
1143  }
1144  else
1145  {
1148 
1149  /* Pop the transaction state stack */
1150  transInvalInfo = myInfo->parent;
1151 
1152  /* Need not free anything else explicitly */
1153  pfree(myInfo);
1154  }
1155 }
static void ProcessInvalidationMessages(InvalidationMsgsGroup *group, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:515
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:238
static void AppendInvalidationMessages(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src)
Definition: inval.c:501
#define SetGroupToFollow(targetgroup, priorgroup)
Definition: inval.c:189
void CommandEndInvalidationMessages(void)
Definition: inval.c:1173
void pfree(void *pointer)
Definition: mcxt.c:1456
struct TransInvalidationInfo * parent
Definition: inval.c:223
InvalidationMsgsGroup CurrentCmdInvalidMsgs
Definition: inval.c:229
InvalidationMsgsGroup PriorCmdInvalidMsgs
Definition: inval.c:232
bool RelcacheInitFileInval
Definition: inval.c:235
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:914

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_Inval()

void AtEOXact_Inval ( bool  isCommit)

Definition at line 1028 of file inval.c.

1029 {
1030  /* Quick exit if no messages */
1031  if (transInvalInfo == NULL)
1032  return;
1033 
1034  /* Must be at top of stack */
1035  Assert(transInvalInfo->my_level == 1 && transInvalInfo->parent == NULL);
1036 
1037  if (isCommit)
1038  {
1039  /*
1040  * Relcache init file invalidation requires processing both before and
1041  * after we send the SI messages. However, we need not do anything
1042  * unless we committed.
1043  */
1046 
1049 
1052 
1055  }
1056  else
1057  {
1060  }
1061 
1062  /* Need not free anything explicitly */
1063  transInvalInfo = NULL;
1064 }
static void ProcessInvalidationMessagesMulti(InvalidationMsgsGroup *group, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:527
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6761
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:6736
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49

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

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

◆ CacheInvalidateCatalog()

void CacheInvalidateCatalog ( Oid  catalogId)

Definition at line 1339 of file inval.c.

1340 {
1341  Oid databaseId;
1342 
1344 
1345  if (IsSharedRelation(catalogId))
1346  databaseId = InvalidOid;
1347  else
1348  databaseId = MyDatabaseId;
1349 
1350  RegisterCatalogInvalidation(databaseId, catalogId);
1351 }
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:245
Oid MyDatabaseId
Definition: globals.c:89
static void PrepareInvalidationState(void)
Definition: inval.c:795
static void RegisterCatalogInvalidation(Oid dbId, Oid catId)
Definition: inval.c:559
unsigned int Oid
Definition: postgres_ext.h:31

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

Referenced by finish_heap_swap().

◆ CacheInvalidateHeapTuple()

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

Definition at line 1207 of file inval.c.

1210 {
1211  Oid tupleRelId;
1212  Oid databaseId;
1213  Oid relationId;
1214 
1215  /* Do nothing during bootstrap */
1217  return;
1218 
1219  /*
1220  * We only need to worry about invalidation for tuples that are in system
1221  * catalogs; user-relation tuples are never in catcaches and can't affect
1222  * the relcache either.
1223  */
1224  if (!IsCatalogRelation(relation))
1225  return;
1226 
1227  /*
1228  * IsCatalogRelation() will return true for TOAST tables of system
1229  * catalogs, but we don't care about those, either.
1230  */
1231  if (IsToastRelation(relation))
1232  return;
1233 
1234  /*
1235  * If we're not prepared to queue invalidation messages for this
1236  * subtransaction level, get ready now.
1237  */
1239 
1240  /*
1241  * First let the catcache do its thing
1242  */
1243  tupleRelId = RelationGetRelid(relation);
1244  if (RelationInvalidatesSnapshotsOnly(tupleRelId))
1245  {
1246  databaseId = IsSharedRelation(tupleRelId) ? InvalidOid : MyDatabaseId;
1247  RegisterSnapshotInvalidation(databaseId, tupleRelId);
1248  }
1249  else
1250  PrepareToInvalidateCacheTuple(relation, tuple, newtuple,
1252 
1253  /*
1254  * Now, is this tuple one of the primary definers of a relcache entry? See
1255  * comments in file header for deeper explanation.
1256  *
1257  * Note we ignore newtuple here; we assume an update cannot move a tuple
1258  * from being part of one relcache entry to being part of another.
1259  */
1260  if (tupleRelId == RelationRelationId)
1261  {
1262  Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple);
1263 
1264  relationId = classtup->oid;
1265  if (classtup->relisshared)
1266  databaseId = InvalidOid;
1267  else
1268  databaseId = MyDatabaseId;
1269  }
1270  else if (tupleRelId == AttributeRelationId)
1271  {
1272  Form_pg_attribute atttup = (Form_pg_attribute) GETSTRUCT(tuple);
1273 
1274  relationId = atttup->attrelid;
1275 
1276  /*
1277  * KLUGE ALERT: we always send the relcache event with MyDatabaseId,
1278  * even if the rel in question is shared (which we can't easily tell).
1279  * This essentially means that only backends in this same database
1280  * will react to the relcache flush request. This is in fact
1281  * appropriate, since only those backends could see our pg_attribute
1282  * change anyway. It looks a bit ugly though. (In practice, shared
1283  * relations can't have schema changes after bootstrap, so we should
1284  * never come here for a shared rel anyway.)
1285  */
1286  databaseId = MyDatabaseId;
1287  }
1288  else if (tupleRelId == IndexRelationId)
1289  {
1290  Form_pg_index indextup = (Form_pg_index) GETSTRUCT(tuple);
1291 
1292  /*
1293  * When a pg_index row is updated, we should send out a relcache inval
1294  * for the index relation. As above, we don't know the shared status
1295  * of the index, but in practice it doesn't matter since indexes of
1296  * shared catalogs can't have such updates.
1297  */
1298  relationId = indextup->indexrelid;
1299  databaseId = MyDatabaseId;
1300  }
1301  else if (tupleRelId == ConstraintRelationId)
1302  {
1303  Form_pg_constraint constrtup = (Form_pg_constraint) GETSTRUCT(tuple);
1304 
1305  /*
1306  * Foreign keys are part of relcache entries, too, so send out an
1307  * inval for the table that the FK applies to.
1308  */
1309  if (constrtup->contype == CONSTRAINT_FOREIGN &&
1310  OidIsValid(constrtup->conrelid))
1311  {
1312  relationId = constrtup->conrelid;
1313  databaseId = MyDatabaseId;
1314  }
1315  else
1316  return;
1317  }
1318  else
1319  return;
1320 
1321  /*
1322  * Yes. We need to register a relcache invalidation event.
1323  */
1324  RegisterRelcacheInvalidation(databaseId, relationId);
1325 }
#define OidIsValid(objectId)
Definition: c.h:764
bool IsToastRelation(Relation relation)
Definition: catalog.c:147
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:105
void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
Definition: catcache.c:2003
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static void RegisterSnapshotInvalidation(Oid dbId, Oid relId)
Definition: inval.c:601
static void RegisterCatcacheInvalidation(int cacheId, uint32 hashValue, Oid dbId)
Definition: inval.c:545
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:571
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
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:504
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1203

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().

◆ CacheInvalidateRelcache()

◆ CacheInvalidateRelcacheAll()

void CacheInvalidateRelcacheAll ( void  )

◆ CacheInvalidateRelcacheByRelid()

void CacheInvalidateRelcacheByRelid ( Oid  relid)

Definition at line 1422 of file inval.c.

1423 {
1424  HeapTuple tup;
1425 
1427 
1428  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1429  if (!HeapTupleIsValid(tup))
1430  elog(ERROR, "cache lookup failed for relation %u", relid);
1432  ReleaseSysCache(tup);
1433 }
#define ERROR
Definition: elog.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1399
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
@ RELOID
Definition: syscache.h:89

References CacheInvalidateRelcacheByTuple(), elog(), ERROR, HeapTupleIsValid, ObjectIdGetDatum(), PrepareInvalidationState(), ReleaseSysCache(), RELOID, 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 1399 of file inval.c.

1400 {
1401  Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple);
1402  Oid databaseId;
1403  Oid relationId;
1404 
1406 
1407  relationId = classtup->oid;
1408  if (classtup->relisshared)
1409  databaseId = InvalidOid;
1410  else
1411  databaseId = MyDatabaseId;
1412  RegisterRelcacheInvalidation(databaseId, relationId);
1413 }

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 1492 of file inval.c.

1493 {
1495 
1496  msg.rm.id = SHAREDINVALRELMAP_ID;
1497  msg.rm.dbId = databaseId;
1498  /* check AddCatcacheInvalidationMessage() for an explanation */
1499  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1500 
1501  SendSharedInvalidMessages(&msg, 1);
1502 }
#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 1462 of file inval.c.

1463 {
1465 
1466  msg.sm.id = SHAREDINVALSMGR_ID;
1467  msg.sm.backend_hi = rlocator.backend >> 16;
1468  msg.sm.backend_lo = rlocator.backend & 0xffff;
1469  msg.sm.rlocator = rlocator.locator;
1470  /* check AddCatcacheInvalidationMessage() for an explanation */
1471  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1472 
1473  SendSharedInvalidMessages(&msg, 1);
1474 }
#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 1561 of file inval.c.

1563 {
1565  elog(FATAL, "out of relcache_callback_list slots");
1566 
1569 
1571 }
#define FATAL
Definition: elog.h:41
static int relcache_callback_count
Definition: inval.c:274
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
#define MAX_RELCACHE_CALLBACKS
Definition: inval.c:254
void * arg
RelcacheCallbackFunction function
Definition: inval.c:270

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 1519 of file inval.c.

1522 {
1523  if (cacheid < 0 || cacheid >= SysCacheSize)
1524  elog(FATAL, "invalid cache ID: %d", cacheid);
1526  elog(FATAL, "out of syscache_callback_list slots");
1527 
1528  if (syscache_callback_links[cacheid] == 0)
1529  {
1530  /* first callback for this cache */
1532  }
1533  else
1534  {
1535  /* add to end of chain, so that older callbacks are called first */
1536  int i = syscache_callback_links[cacheid] - 1;
1537 
1538  while (syscache_callback_list[i].link > 0)
1539  i = syscache_callback_list[i].link - 1;
1541  }
1542 
1547 
1549 }
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
#define MAX_SYSCACHE_CALLBACKS
Definition: inval.c:253
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:264
static int syscache_callback_count
Definition: inval.c:266
int i
Definition: isn.c:73
SyscacheCallbackFunction function
Definition: inval.c:260
int16 link
Definition: inval.c:259
#define SysCacheSize
Definition: syscache.h:118

References SYSCACHECALLBACK::arg, 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 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 1580 of file inval.c.

1581 {
1582  int i;
1583 
1584  if (cacheid < 0 || cacheid >= SysCacheSize)
1585  elog(ERROR, "invalid cache ID: %d", cacheid);
1586 
1587  i = syscache_callback_links[cacheid] - 1;
1588  while (i >= 0)
1589  {
1590  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
1591 
1592  Assert(ccitem->id == cacheid);
1593  ccitem->function(ccitem->arg, cacheid, hashvalue);
1594  i = ccitem->link - 1;
1595  }
1596 }

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().

◆ CommandEndInvalidationMessages()

void CommandEndInvalidationMessages ( void  )

Definition at line 1173 of file inval.c.

1174 {
1175  /*
1176  * You might think this shouldn't be called outside any transaction, but
1177  * bootstrap does it, and also ABORT issued when not in a transaction. So
1178  * just quietly return if no state to work on.
1179  */
1180  if (transInvalInfo == NULL)
1181  return;
1182 
1185 
1186  /* WAL Log per-command invalidation messages for wal_level=logical */
1187  if (XLogLogicalInfoActive())
1189 
1192 }
void LogLogicalInvalidations(void)
Definition: inval.c:1607
#define XLogLogicalInfoActive()
Definition: xlog.h:121

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

Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().

◆ InvalidateSystemCaches()

void InvalidateSystemCaches ( void  )

◆ InvalidateSystemCachesExtended()

void InvalidateSystemCachesExtended ( bool  debug_discard)

Definition at line 708 of file inval.c.

709 {
710  int i;
711 
714  RelationCacheInvalidate(debug_discard); /* gets smgr and relmap too */
715 
716  for (i = 0; i < syscache_callback_count; i++)
717  {
718  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
719 
720  ccitem->function(ccitem->arg, ccitem->id, 0);
721  }
722 
723  for (i = 0; i < relcache_callback_count; i++)
724  {
725  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
726 
727  ccitem->function(ccitem->arg, InvalidOid);
728  }
729 }
void ResetCatalogCaches(void)
Definition: catcache.c:683
void RelationCacheInvalidate(bool debug_discard)
Definition: relcache.c:2934
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:403

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(), and InvalidateSystemCaches().

◆ LocalExecuteInvalidationMessage()

void LocalExecuteInvalidationMessage ( SharedInvalidationMessage msg)

Definition at line 615 of file inval.c.

616 {
617  if (msg->id >= 0)
618  {
619  if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
620  {
622 
623  SysCacheInvalidate(msg->cc.id, msg->cc.hashValue);
624 
625  CallSyscacheCallbacks(msg->cc.id, msg->cc.hashValue);
626  }
627  }
628  else if (msg->id == SHAREDINVALCATALOG_ID)
629  {
630  if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
631  {
633 
635 
636  /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
637  }
638  }
639  else if (msg->id == SHAREDINVALRELCACHE_ID)
640  {
641  if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
642  {
643  int i;
644 
645  if (msg->rc.relId == InvalidOid)
647  else
649 
650  for (i = 0; i < relcache_callback_count; i++)
651  {
652  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
653 
654  ccitem->function(ccitem->arg, msg->rc.relId);
655  }
656  }
657  }
658  else if (msg->id == SHAREDINVALSMGR_ID)
659  {
660  /*
661  * We could have smgr entries for relations of other databases, so no
662  * short-circuit test is possible here.
663  */
664  RelFileLocatorBackend rlocator;
665 
666  rlocator.locator = msg->sm.rlocator;
667  rlocator.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
668  smgrcloserellocator(rlocator);
669  }
670  else if (msg->id == SHAREDINVALRELMAP_ID)
671  {
672  /* We only care about our own database and shared catalogs */
673  if (msg->rm.dbId == InvalidOid)
674  RelationMapInvalidate(true);
675  else if (msg->rm.dbId == MyDatabaseId)
676  RelationMapInvalidate(false);
677  }
678  else if (msg->id == SHAREDINVALSNAPSHOT_ID)
679  {
680  /* We only care about our own database and shared catalogs */
681  if (msg->sn.dbId == InvalidOid)
683  else if (msg->sn.dbId == MyDatabaseId)
685  }
686  else
687  elog(FATAL, "unrecognized SI message ID: %d", msg->id);
688 }
void CatalogCacheFlushCatalog(Oid catId)
Definition: catcache.c:713
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1580
void RelationCacheInvalidateEntry(Oid relationId)
Definition: relcache.c:2878
void RelationMapInvalidate(bool shared)
Definition: relmapper.c:468
void smgrcloserellocator(RelFileLocatorBackend rlocator)
Definition: smgr.c:351
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:1179

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, smgrcloserellocator(), SharedInvalidationMessage::sn, and SysCacheInvalidate().

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

◆ LogLogicalInvalidations()

void LogLogicalInvalidations ( void  )

Definition at line 1607 of file inval.c.

1608 {
1609  xl_xact_invals xlrec;
1610  InvalidationMsgsGroup *group;
1611  int nmsgs;
1612 
1613  /* Quick exit if we haven't done anything with invalidation messages. */
1614  if (transInvalInfo == NULL)
1615  return;
1616 
1618  nmsgs = NumMessagesInGroup(group);
1619 
1620  if (nmsgs > 0)
1621  {
1622  /* prepare record */
1623  memset(&xlrec, 0, MinSizeOfXactInvals);
1624  xlrec.nmsgs = nmsgs;
1625 
1626  /* perform insertion */
1627  XLogBeginInsert();
1628  XLogRegisterData((char *) (&xlrec), MinSizeOfXactInvals);
1630  XLogRegisterData((char *) msgs,
1631  n * sizeof(SharedInvalidationMessage)));
1633  XLogRegisterData((char *) msgs,
1634  n * sizeof(SharedInvalidationMessage)));
1635  XLogInsert(RM_XACT_ID, XLOG_XACT_INVALIDATIONS);
1636  }
1637 }
#define NumMessagesInGroup(group)
Definition: inval.c:198
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
Definition: inval.c:373
int nmsgs
Definition: xact.h:298
#define MinSizeOfXactInvals
Definition: xact.h:301
#define XLOG_XACT_INVALIDATIONS
Definition: xact.h:175
void XLogRegisterData(char *data, uint32 len)
Definition: xloginsert.c:351
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:461
void XLogBeginInsert(void)
Definition: xloginsert.c:150

References CatCacheMsgs, TransInvalidationInfo::CurrentCmdInvalidMsgs, 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 865 of file inval.c.

866 {
867  AtEOXact_Inval(false);
868 }
void AtEOXact_Inval(bool isCommit)
Definition: inval.c:1028

References AtEOXact_Inval().

Referenced by PrepareTransaction().

◆ PrepareInvalidationState()

static void PrepareInvalidationState ( void  )
static

Definition at line 795 of file inval.c.

796 {
797  TransInvalidationInfo *myInfo;
798 
799  if (transInvalInfo != NULL &&
801  return;
802 
803  myInfo = (TransInvalidationInfo *)
805  sizeof(TransInvalidationInfo));
806  myInfo->parent = transInvalInfo;
808 
809  /* Now, do we have a previous stack entry? */
810  if (transInvalInfo != NULL)
811  {
812  /* Yes; this one should be for a deeper nesting level. */
814 
815  /*
816  * The parent (sub)transaction must not have any current (i.e.,
817  * not-yet-locally-processed) messages. If it did, we'd have a
818  * semantic problem: the new subtransaction presumably ought not be
819  * able to see those events yet, but since the CommandCounter is
820  * linear, that can't work once the subtransaction advances the
821  * counter. This is a convenient place to check for that, as well as
822  * being important to keep management of the message arrays simple.
823  */
825  elog(ERROR, "cannot start a subtransaction when there are unprocessed inval messages");
826 
827  /*
828  * MemoryContextAllocZero set firstmsg = nextmsg = 0 in each group,
829  * which is fine for the first (sub)transaction, but otherwise we need
830  * to update them to follow whatever is already in the arrays.
831  */
835  &myInfo->PriorCmdInvalidMsgs);
836  }
837  else
838  {
839  /*
840  * Here, we need only clear any array pointers left over from a prior
841  * transaction.
842  */
847  }
848 
849  transInvalInfo = myInfo;
850 }
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064

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

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

◆ ProcessCommittedInvalidationMessages()

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

Definition at line 963 of file inval.c.

966 {
967  if (nmsgs <= 0)
968  return;
969 
970  elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
971  (RelcacheInitFileInval ? " and relcache file invalidation" : ""));
972 
973  if (RelcacheInitFileInval)
974  {
975  elog(trace_recovery(DEBUG4), "removing relcache init files for database %u",
976  dbid);
977 
978  /*
979  * RelationCacheInitFilePreInvalidate, when the invalidation message
980  * is for a specific database, requires DatabasePath to be set, but we
981  * should not use SetDatabasePath during recovery, since it is
982  * intended to be used only once by normal backends. Hence, a quick
983  * hack: set DatabasePath directly then unset after use.
984  */
985  if (OidIsValid(dbid))
986  DatabasePath = GetDatabasePath(dbid, tsid);
987 
989 
990  if (OidIsValid(dbid))
991  {
993  DatabasePath = NULL;
994  }
995  }
996 
997  SendSharedInvalidMessages(msgs, nmsgs);
998 
999  if (RelcacheInitFileInval)
1001 }
int trace_recovery(int trace_level)
Definition: elog.c:3752
#define DEBUG4
Definition: elog.h:27
char * DatabasePath
Definition: globals.c:97
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110

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

Referenced by standby_redo(), and xact_redo_commit().

◆ ProcessInvalidationMessages()

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

Definition at line 515 of file inval.c.

517 {
518  ProcessMessageSubGroup(group, CatCacheMsgs, func(msg));
519  ProcessMessageSubGroup(group, RelCacheMsgs, func(msg));
520 }

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 527 of file inval.c.

529 {
530  ProcessMessageSubGroupMulti(group, CatCacheMsgs, func(msgs, n));
531  ProcessMessageSubGroupMulti(group, RelCacheMsgs, func(msgs, n));
532 }

References CatCacheMsgs, ProcessMessageSubGroupMulti, and RelCacheMsgs.

Referenced by AtEOXact_Inval().

◆ RegisterCatalogInvalidation()

static void RegisterCatalogInvalidation ( Oid  dbId,
Oid  catId 
)
static

Definition at line 559 of file inval.c.

560 {
562  dbId, catId);
563 }
static void AddCatalogInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid catId)
Definition: inval.c:424

References AddCatalogInvalidationMessage(), TransInvalidationInfo::CurrentCmdInvalidMsgs, and transInvalInfo.

Referenced by CacheInvalidateCatalog().

◆ RegisterCatcacheInvalidation()

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

Definition at line 545 of file inval.c.

548 {
550  cacheId, hashValue, dbId);
551 }
static void AddCatcacheInvalidationMessage(InvalidationMsgsGroup *group, int id, uint32 hashValue, Oid dbId)
Definition: inval.c:396

References AddCatcacheInvalidationMessage(), TransInvalidationInfo::CurrentCmdInvalidMsgs, and transInvalInfo.

Referenced by CacheInvalidateHeapTuple().

◆ RegisterRelcacheInvalidation()

static void RegisterRelcacheInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 571 of file inval.c.

572 {
574  dbId, relId);
575 
576  /*
577  * Most of the time, relcache invalidation is associated with system
578  * catalog updates, but there are a few cases where it isn't. Quick hack
579  * to ensure that the next CommandCounterIncrement() will think that we
580  * need to do CommandEndInvalidationMessages().
581  */
582  (void) GetCurrentCommandId(true);
583 
584  /*
585  * If the relation being invalidated is one of those cached in a relcache
586  * init file, mark that we need to zap that file at commit. For simplicity
587  * invalidations for a specific database always invalidate the shared file
588  * as well. Also zap when we are invalidating whole relcache.
589  */
590  if (relId == InvalidOid || RelationIdIsInInitFile(relId))
592 }
static void AddRelcacheInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
Definition: inval.c:442
bool RelationIdIsInInitFile(Oid relationId)
Definition: relcache.c:6696
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:818

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

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

◆ RegisterSnapshotInvalidation()

static void RegisterSnapshotInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 601 of file inval.c.

602 {
604  dbId, relId);
605 }
static void AddSnapshotInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
Definition: inval.c:474

References AddSnapshotInvalidationMessage(), TransInvalidationInfo::CurrentCmdInvalidMsgs, and transInvalInfo.

Referenced by CacheInvalidateHeapTuple().

◆ xactGetCommittedInvalidationMessages()

int xactGetCommittedInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool RelcacheInitFileInval 
)

Definition at line 884 of file inval.c.

886 {
887  SharedInvalidationMessage *msgarray;
888  int nummsgs;
889  int nmsgs;
890 
891  /* Quick exit if we haven't done anything with invalidation messages. */
892  if (transInvalInfo == NULL)
893  {
894  *RelcacheInitFileInval = false;
895  *msgs = NULL;
896  return 0;
897  }
898 
899  /* Must be at top of stack */
901 
902  /*
903  * Relcache init file invalidation requires processing both before and
904  * after we send the SI messages. However, we need not do anything unless
905  * we committed.
906  */
907  *RelcacheInitFileInval = transInvalInfo->RelcacheInitFileInval;
908 
909  /*
910  * Collect all the pending messages into a single contiguous array of
911  * invalidation messages, to simplify what needs to happen while building
912  * the commit WAL message. Maintain the order that they would be
913  * processed in by AtEOXact_Inval(), to ensure emulated behaviour in redo
914  * is as similar as possible to original. We want the same bugs, if any,
915  * not new ones.
916  */
919 
920  *msgs = msgarray = (SharedInvalidationMessage *)
922  nummsgs * sizeof(SharedInvalidationMessage));
923 
924  nmsgs = 0;
926  CatCacheMsgs,
927  (memcpy(msgarray + nmsgs,
928  msgs,
929  n * sizeof(SharedInvalidationMessage)),
930  nmsgs += n));
932  CatCacheMsgs,
933  (memcpy(msgarray + nmsgs,
934  msgs,
935  n * sizeof(SharedInvalidationMessage)),
936  nmsgs += n));
938  RelCacheMsgs,
939  (memcpy(msgarray + nmsgs,
940  msgs,
941  n * sizeof(SharedInvalidationMessage)),
942  nmsgs += n));
944  RelCacheMsgs,
945  (memcpy(msgarray + nmsgs,
946  msgs,
947  n * sizeof(SharedInvalidationMessage)),
948  nmsgs += n));
949  Assert(nmsgs == nummsgs);
950 
951  return nmsgs;
952 }
MemoryContext CurTransactionContext
Definition: mcxt.c:147

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

Referenced by RecordTransactionCommit(), and StartPrepare().

Variable Documentation

◆ debug_discard_caches

int debug_discard_caches = 0

Definition at line 241 of file inval.c.

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

◆ InvalMessageArrays

InvalMessageArray InvalMessageArrays[2]
static

Definition at line 172 of file inval.c.

Referenced by AddInvalidationMessage(), and PrepareInvalidationState().

◆ relcache_callback_count

int relcache_callback_count = 0
static

◆ relcache_callback_list

◆ syscache_callback_count

int syscache_callback_count = 0
static

Definition at line 266 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and InvalidateSystemCachesExtended().

◆ syscache_callback_links

int16 syscache_callback_links[SysCacheSize]
static

Definition at line 264 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and CallSyscacheCallbacks().

◆ syscache_callback_list

◆ transInvalInfo