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

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

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

1084 {
1085  int my_level;
1087 
1088  /* Quick exit if no messages. */
1089  if (myInfo == NULL)
1090  return;
1091 
1092  /* Also bail out quickly if messages are not for this level. */
1093  my_level = GetCurrentTransactionNestLevel();
1094  if (myInfo->my_level != my_level)
1095  {
1096  Assert(myInfo->my_level < my_level);
1097  return;
1098  }
1099 
1100  if (isCommit)
1101  {
1102  /* If CurrentCmdInvalidMsgs still has anything, fix it */
1104 
1105  /*
1106  * We create invalidation stack entries lazily, so the parent might
1107  * not have one. Instead of creating one, moving all the data over,
1108  * and then freeing our own, we can just adjust the level of our own
1109  * entry.
1110  */
1111  if (myInfo->parent == NULL || myInfo->parent->my_level < my_level - 1)
1112  {
1113  myInfo->my_level--;
1114  return;
1115  }
1116 
1117  /*
1118  * Pass up my inval messages to parent. Notice that we stick them in
1119  * PriorCmdInvalidMsgs, not CurrentCmdInvalidMsgs, since they've
1120  * already been locally processed. (This would trigger the Assert in
1121  * AppendInvalidationMessageSubGroup if the parent's
1122  * CurrentCmdInvalidMsgs isn't empty; but we already checked that in
1123  * PrepareInvalidationState.)
1124  */
1126  &myInfo->PriorCmdInvalidMsgs);
1127 
1128  /* Must readjust parent's CurrentCmdInvalidMsgs indexes now */
1130  &myInfo->parent->PriorCmdInvalidMsgs);
1131 
1132  /* Pending relcache inval becomes parent's problem too */
1133  if (myInfo->RelcacheInitFileInval)
1134  myInfo->parent->RelcacheInitFileInval = true;
1135 
1136  /* Pop the transaction state stack */
1137  transInvalInfo = myInfo->parent;
1138 
1139  /* Need not free anything else explicitly */
1140  pfree(myInfo);
1141  }
1142  else
1143  {
1146 
1147  /* Pop the transaction state stack */
1148  transInvalInfo = myInfo->parent;
1149 
1150  /* Need not free anything else explicitly */
1151  pfree(myInfo);
1152  }
1153 }
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:1171
void pfree(void *pointer)
Definition: mcxt.c:1431
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 1026 of file inval.c.

1027 {
1028  /* Quick exit if no messages */
1029  if (transInvalInfo == NULL)
1030  return;
1031 
1032  /* Must be at top of stack */
1033  Assert(transInvalInfo->my_level == 1 && transInvalInfo->parent == NULL);
1034 
1035  if (isCommit)
1036  {
1037  /*
1038  * Relcache init file invalidation requires processing both before and
1039  * after we send the SI messages. However, we need not do anything
1040  * unless we committed.
1041  */
1044 
1047 
1050 
1053  }
1054  else
1055  {
1058  }
1059 
1060  /* Need not free anything explicitly */
1061  transInvalInfo = NULL;
1062 }
static void ProcessInvalidationMessagesMulti(InvalidationMsgsGroup *group, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:527
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6753
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:6728
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 1337 of file inval.c.

1338 {
1339  Oid databaseId;
1340 
1342 
1343  if (IsSharedRelation(catalogId))
1344  databaseId = InvalidOid;
1345  else
1346  databaseId = MyDatabaseId;
1347 
1348  RegisterCatalogInvalidation(databaseId, catalogId);
1349 }
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:245
Oid MyDatabaseId
Definition: globals.c:90
static void PrepareInvalidationState(void)
Definition: inval.c:612
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 1205 of file inval.c.

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

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

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

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

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

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

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

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

1561 {
1563  elog(FATAL, "out of relcache_callback_list slots");
1564 
1567 
1569 }
#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 1517 of file inval.c.

1520 {
1521  if (cacheid < 0 || cacheid >= SysCacheSize)
1522  elog(FATAL, "invalid cache ID: %d", cacheid);
1524  elog(FATAL, "out of syscache_callback_list slots");
1525 
1526  if (syscache_callback_links[cacheid] == 0)
1527  {
1528  /* first callback for this cache */
1530  }
1531  else
1532  {
1533  /* add to end of chain, so that older callbacks are called first */
1534  int i = syscache_callback_links[cacheid] - 1;
1535 
1536  while (syscache_callback_list[i].link > 0)
1537  i = syscache_callback_list[i].link - 1;
1539  }
1540 
1545 
1547 }
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

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

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

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

1172 {
1173  /*
1174  * You might think this shouldn't be called outside any transaction, but
1175  * bootstrap does it, and also ABORT issued when not in a transaction. So
1176  * just quietly return if no state to work on.
1177  */
1178  if (transInvalInfo == NULL)
1179  return;
1180 
1183 
1184  /* WAL Log per-command invalidation messages for wal_level=logical */
1185  if (XLogLogicalInfoActive())
1187 
1190 }
void LogLogicalInvalidations(void)
Definition: inval.c:1605
#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 675 of file inval.c.

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

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

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

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

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

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

References AtEOXact_Inval().

Referenced by PrepareTransaction().

◆ PrepareInvalidationState()

static void PrepareInvalidationState ( void  )
static

Definition at line 612 of file inval.c.

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

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

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

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