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

Go to the source code of this file.

Data Structures

struct  InvalMessageArray
 
struct  InvalidationMsgsGroup
 
struct  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)
 
static void PrepareInvalidationState (void)
 
void InvalidateSystemCachesExtended (bool debug_discard)
 
void LocalExecuteInvalidationMessage (SharedInvalidationMessage *msg)
 
void InvalidateSystemCaches (void)
 
void AcceptInvalidationMessages (void)
 
void PostPrepare_Inval (void)
 
int xactGetCommittedInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
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 161 of file inval.c.

◆ MAX_RELCACHE_CALLBACKS

#define MAX_RELCACHE_CALLBACKS   10

Definition at line 253 of file inval.c.

◆ MAX_SYSCACHE_CALLBACKS

#define MAX_SYSCACHE_CALLBACKS   64

Definition at line 252 of file inval.c.

◆ NumMessagesInGroup

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

Definition at line 197 of file inval.c.

◆ NumMessagesInSubGroup

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

Definition at line 194 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:171
SharedInvalidationMessage * msgs
Definition: inval.c:167

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

◆ RelCacheMsgs

#define RelCacheMsgs   1

Definition at line 162 of file inval.c.

◆ SetGroupToFollow

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

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

Typedef Documentation

◆ InvalidationMsgsGroup

◆ InvalMessageArray

◆ TransInvalidationInfo

Function Documentation

◆ AcceptInvalidationMessages()

void AcceptInvalidationMessages ( void  )

Definition at line 806 of file inval.c.

807 {
810 
811  /*----------
812  * Test code to force cache flushes anytime a flush could happen.
813  *
814  * This helps detect intermittent faults caused by code that reads a cache
815  * entry and then performs an action that could invalidate the entry, but
816  * rarely actually does so. This can spot issues that would otherwise
817  * only arise with badly timed concurrent DDL, for example.
818  *
819  * The default debug_discard_caches = 0 does no forced cache flushes.
820  *
821  * If used with CLOBBER_FREED_MEMORY,
822  * debug_discard_caches = 1 (formerly known as CLOBBER_CACHE_ALWAYS)
823  * provides a fairly thorough test that the system contains no cache-flush
824  * hazards. However, it also makes the system unbelievably slow --- the
825  * regression tests take about 100 times longer than normal.
826  *
827  * If you're a glutton for punishment, try
828  * debug_discard_caches = 3 (formerly known as CLOBBER_CACHE_RECURSIVELY).
829  * This slows things by at least a factor of 10000, so I wouldn't suggest
830  * trying to run the entire regression tests that way. It's useful to try
831  * a few simple tests, to make sure that cache reload isn't subject to
832  * internal cache-flush hazards, but after you've done a few thousand
833  * recursive reloads it's unlikely you'll learn more.
834  *----------
835  */
836 #ifdef DISCARD_CACHES_ENABLED
837  {
838  static int recursion_depth = 0;
839 
841  {
842  recursion_depth++;
844  recursion_depth--;
845  }
846  }
847 #endif
848 }
static int recursion_depth
Definition: elog.c:153
void InvalidateSystemCachesExtended(bool debug_discard)
Definition: inval.c:674
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:705
void InvalidateSystemCaches(void)
Definition: inval.c:792
int debug_discard_caches
Definition: inval.c:240
void ReceiveSharedInvalidMessages(void(*invalFunction)(SharedInvalidationMessage *msg), void(*resetFunction)(void))
Definition: sinval.c:69

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

Referenced by apply_handle_commit_internal(), AtStart_Cache(), ConditionalLockRelation(), ConditionalLockRelationOid(), ConditionalLockSharedObject(), 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 423 of file inval.c.

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

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

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

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

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

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

502 {
505 }
static void AppendInvalidationMessageSubGroup(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src, int subgroup)
Definition: inval.c:330

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

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

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

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

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

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

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

1337 {
1338  Oid databaseId;
1339 
1341 
1342  if (IsSharedRelation(catalogId))
1343  databaseId = InvalidOid;
1344  else
1345  databaseId = MyDatabaseId;
1346 
1347  RegisterCatalogInvalidation(databaseId, catalogId);
1348 }
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:243
Oid MyDatabaseId
Definition: globals.c:91
static void PrepareInvalidationState(void)
Definition: inval.c:611
static void RegisterCatalogInvalidation(Oid dbId, Oid catId)
Definition: inval.c:558
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 1204 of file inval.c.

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

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

1420 {
1421  HeapTuple tup;
1422 
1424 
1425  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1426  if (!HeapTupleIsValid(tup))
1427  elog(ERROR, "cache lookup failed for relation %u", relid);
1429  ReleaseSysCache(tup);
1430 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1396
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218

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

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

◆ CacheInvalidateRelcacheByTuple()

void CacheInvalidateRelcacheByTuple ( HeapTuple  classTuple)

Definition at line 1396 of file inval.c.

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

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

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

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

1560 {
1562  elog(FATAL, "out of relcache_callback_list slots");
1563 
1566 
1568 }
#define FATAL
Definition: elog.h:41
static int relcache_callback_count
Definition: inval.c:273
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
#define MAX_RELCACHE_CALLBACKS
Definition: inval.c:253
void * arg
RelcacheCallbackFunction function
Definition: inval.c:269

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

1519 {
1520  if (cacheid < 0 || cacheid >= SysCacheSize)
1521  elog(FATAL, "invalid cache ID: %d", cacheid);
1523  elog(FATAL, "out of syscache_callback_list slots");
1524 
1525  if (syscache_callback_links[cacheid] == 0)
1526  {
1527  /* first callback for this cache */
1529  }
1530  else
1531  {
1532  /* add to end of chain, so that older callbacks are called first */
1533  int i = syscache_callback_links[cacheid] - 1;
1534 
1535  while (syscache_callback_list[i].link > 0)
1536  i = syscache_callback_list[i].link - 1;
1538  }
1539 
1544 
1546 }
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
#define MAX_SYSCACHE_CALLBACKS
Definition: inval.c:252
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:263
static int syscache_callback_count
Definition: inval.c:265
int i
Definition: isn.c:73
SyscacheCallbackFunction function
Definition: inval.c:259
int16 link
Definition: inval.c:258

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

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

◆ CallSyscacheCallbacks()

void CallSyscacheCallbacks ( int  cacheid,
uint32  hashvalue 
)

Definition at line 1577 of file inval.c.

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

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

Referenced by CatalogCacheFlushCatalog(), and LocalExecuteInvalidationMessage().

◆ CommandEndInvalidationMessages()

void CommandEndInvalidationMessages ( void  )

Definition at line 1170 of file inval.c.

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

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

Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().

◆ InvalidateSystemCaches()

◆ InvalidateSystemCachesExtended()

void InvalidateSystemCachesExtended ( bool  debug_discard)

Definition at line 674 of file inval.c.

675 {
676  int i;
677 
680  RelationCacheInvalidate(debug_discard); /* gets smgr and relmap too */
681 
682  for (i = 0; i < syscache_callback_count; i++)
683  {
684  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
685 
686  ccitem->function(ccitem->arg, ccitem->id, 0);
687  }
688 
689  for (i = 0; i < relcache_callback_count; i++)
690  {
691  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
692 
693  ccitem->function(ccitem->arg, InvalidOid);
694  }
695 }
void ResetCatalogCaches(void)
Definition: catcache.c:735
void RelationCacheInvalidate(bool debug_discard)
Definition: relcache.c:2966
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:422

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

706 {
707  if (msg->id >= 0)
708  {
709  if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
710  {
712 
713  SysCacheInvalidate(msg->cc.id, msg->cc.hashValue);
714 
715  CallSyscacheCallbacks(msg->cc.id, msg->cc.hashValue);
716  }
717  }
718  else if (msg->id == SHAREDINVALCATALOG_ID)
719  {
720  if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
721  {
723 
725 
726  /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
727  }
728  }
729  else if (msg->id == SHAREDINVALRELCACHE_ID)
730  {
731  if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
732  {
733  int i;
734 
735  if (msg->rc.relId == InvalidOid)
737  else
739 
740  for (i = 0; i < relcache_callback_count; i++)
741  {
742  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
743 
744  ccitem->function(ccitem->arg, msg->rc.relId);
745  }
746  }
747  }
748  else if (msg->id == SHAREDINVALSMGR_ID)
749  {
750  /*
751  * We could have smgr entries for relations of other databases, so no
752  * short-circuit test is possible here.
753  */
754  RelFileLocatorBackend rlocator;
755 
756  rlocator.locator = msg->sm.rlocator;
757  rlocator.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
758  smgrreleaserellocator(rlocator);
759  }
760  else if (msg->id == SHAREDINVALRELMAP_ID)
761  {
762  /* We only care about our own database and shared catalogs */
763  if (msg->rm.dbId == InvalidOid)
764  RelationMapInvalidate(true);
765  else if (msg->rm.dbId == MyDatabaseId)
766  RelationMapInvalidate(false);
767  }
768  else if (msg->id == SHAREDINVALSNAPSHOT_ID)
769  {
770  /* We only care about our own database and shared catalogs */
771  if (msg->sn.dbId == InvalidOid)
773  else if (msg->sn.dbId == MyDatabaseId)
775  }
776  else
777  elog(FATAL, "unrecognized SI message ID: %d", msg->id);
778 }
void CatalogCacheFlushCatalog(Oid catId)
Definition: catcache.c:765
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1577
void RelationCacheInvalidateEntry(Oid relationId)
Definition: relcache.c:2910
void RelationMapInvalidate(bool shared)
Definition: relmapper.c:468
void smgrreleaserellocator(RelFileLocatorBackend rlocator)
Definition: smgr.c:379
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:577

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

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

◆ LogLogicalInvalidations()

void LogLogicalInvalidations ( void  )

Definition at line 1604 of file inval.c.

1605 {
1606  xl_xact_invals xlrec;
1607  InvalidationMsgsGroup *group;
1608  int nmsgs;
1609 
1610  /* Quick exit if we haven't done anything with invalidation messages. */
1611  if (transInvalInfo == NULL)
1612  return;
1613 
1615  nmsgs = NumMessagesInGroup(group);
1616 
1617  if (nmsgs > 0)
1618  {
1619  /* prepare record */
1620  memset(&xlrec, 0, MinSizeOfXactInvals);
1621  xlrec.nmsgs = nmsgs;
1622 
1623  /* perform insertion */
1624  XLogBeginInsert();
1625  XLogRegisterData((char *) (&xlrec), MinSizeOfXactInvals);
1627  XLogRegisterData((char *) msgs,
1628  n * sizeof(SharedInvalidationMessage)));
1630  XLogRegisterData((char *) msgs,
1631  n * sizeof(SharedInvalidationMessage)));
1632  XLogInsert(RM_XACT_ID, XLOG_XACT_INVALIDATIONS);
1633  }
1634 }
#define NumMessagesInGroup(group)
Definition: inval.c:197
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
Definition: inval.c:372
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:364
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogBeginInsert(void)
Definition: xloginsert.c:149

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

864 {
865  AtEOXact_Inval(false);
866 }
void AtEOXact_Inval(bool isCommit)
Definition: inval.c:1025

References AtEOXact_Inval().

Referenced by PrepareTransaction().

◆ PrepareInvalidationState()

static void PrepareInvalidationState ( void  )
static

Definition at line 611 of file inval.c.

612 {
613  TransInvalidationInfo *myInfo;
614 
615  if (transInvalInfo != NULL &&
617  return;
618 
619  myInfo = (TransInvalidationInfo *)
621  sizeof(TransInvalidationInfo));
622  myInfo->parent = transInvalInfo;
624 
625  /* Now, do we have a previous stack entry? */
626  if (transInvalInfo != NULL)
627  {
628  /* Yes; this one should be for a deeper nesting level. */
630 
631  /*
632  * The parent (sub)transaction must not have any current (i.e.,
633  * not-yet-locally-processed) messages. If it did, we'd have a
634  * semantic problem: the new subtransaction presumably ought not be
635  * able to see those events yet, but since the CommandCounter is
636  * linear, that can't work once the subtransaction advances the
637  * counter. This is a convenient place to check for that, as well as
638  * being important to keep management of the message arrays simple.
639  */
641  elog(ERROR, "cannot start a subtransaction when there are unprocessed inval messages");
642 
643  /*
644  * MemoryContextAllocZero set firstmsg = nextmsg = 0 in each group,
645  * which is fine for the first (sub)transaction, but otherwise we need
646  * to update them to follow whatever is already in the arrays.
647  */
651  &myInfo->PriorCmdInvalidMsgs);
652  }
653  else
654  {
655  /*
656  * Here, we need only clear any array pointers left over from a prior
657  * transaction.
658  */
663  }
664 
665  transInvalInfo = myInfo;
666 }
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1202

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

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

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

Referenced by standby_redo(), and xact_redo_commit().

◆ ProcessInvalidationMessages()

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

Definition at line 514 of file inval.c.

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

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

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

References CatCacheMsgs, ProcessMessageSubGroupMulti, and RelCacheMsgs.

Referenced by AtEOXact_Inval().

◆ RegisterCatalogInvalidation()

static void RegisterCatalogInvalidation ( Oid  dbId,
Oid  catId 
)
static

Definition at line 558 of file inval.c.

559 {
561  dbId, catId);
562 }
static void AddCatalogInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid catId)
Definition: inval.c:423

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

Referenced by CacheInvalidateCatalog().

◆ RegisterCatcacheInvalidation()

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

Definition at line 544 of file inval.c.

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

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

Referenced by CacheInvalidateHeapTuple().

◆ RegisterRelcacheInvalidation()

static void RegisterRelcacheInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 570 of file inval.c.

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

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

601 {
603  dbId, relId);
604 }
static void AddSnapshotInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
Definition: inval.c:473

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

Referenced by CacheInvalidateHeapTuple().

◆ xactGetCommittedInvalidationMessages()

int xactGetCommittedInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool RelcacheInitFileInval 
)

Definition at line 882 of file inval.c.

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

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

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

◆ InvalMessageArrays

InvalMessageArray InvalMessageArrays[2]
static

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

Referenced by CacheRegisterSyscacheCallback(), and InvalidateSystemCachesExtended().

◆ syscache_callback_links

int16 syscache_callback_links[SysCacheSize]
static

Definition at line 263 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and CallSyscacheCallbacks().

◆ syscache_callback_list

◆ transInvalInfo