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

Go to the source code of this file.

Data Structures

struct  InvalMessageArray
 
struct  InvalidationMsgsGroup
 
struct  TransInvalidationInfo
 
struct  SYSCACHECALLBACK
 
struct  RELCACHECALLBACK
 

Macros

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

Typedefs

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

Functions

static void AddInvalidationMessage (InvalidationMsgsGroup *group, int subgroup, const SharedInvalidationMessage *msg)
 
static void AppendInvalidationMessageSubGroup (InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src, int subgroup)
 
static void AddCatcacheInvalidationMessage (InvalidationMsgsGroup *group, int id, uint32 hashValue, Oid dbId)
 
static void AddCatalogInvalidationMessage (InvalidationMsgsGroup *group, Oid dbId, Oid catId)
 
static void AddRelcacheInvalidationMessage (InvalidationMsgsGroup *group, Oid dbId, Oid relId)
 
static void AddSnapshotInvalidationMessage (InvalidationMsgsGroup *group, Oid dbId, Oid relId)
 
static void AppendInvalidationMessages (InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src)
 
static void ProcessInvalidationMessages (InvalidationMsgsGroup *group, void(*func)(SharedInvalidationMessage *msg))
 
static void ProcessInvalidationMessagesMulti (InvalidationMsgsGroup *group, void(*func)(const SharedInvalidationMessage *msgs, int n))
 
static void RegisterCatcacheInvalidation (int cacheId, uint32 hashValue, Oid dbId)
 
static void RegisterCatalogInvalidation (Oid dbId, Oid catId)
 
static void RegisterRelcacheInvalidation (Oid dbId, Oid relId)
 
static void RegisterSnapshotInvalidation (Oid dbId, Oid relId)
 
void LocalExecuteInvalidationMessage (SharedInvalidationMessage *msg)
 
void InvalidateSystemCaches (void)
 
void InvalidateSystemCachesExtended (bool debug_discard)
 
void AcceptInvalidationMessages (void)
 
static void PrepareInvalidationState (void)
 
void PostPrepare_Inval (void)
 
int xactGetCommittedInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
void ProcessCommittedInvalidationMessages (SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
 
void AtEOXact_Inval (bool isCommit)
 
void AtEOSubXact_Inval (bool isCommit)
 
void CommandEndInvalidationMessages (void)
 
void CacheInvalidateHeapTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple)
 
void CacheInvalidateCatalog (Oid catalogId)
 
void CacheInvalidateRelcache (Relation relation)
 
void CacheInvalidateRelcacheAll (void)
 
void CacheInvalidateRelcacheByTuple (HeapTuple classTuple)
 
void CacheInvalidateRelcacheByRelid (Oid relid)
 
void CacheInvalidateSmgr (RelFileNodeBackend rnode)
 
void CacheInvalidateRelmap (Oid databaseId)
 
void CacheRegisterSyscacheCallback (int cacheid, SyscacheCallbackFunction func, Datum arg)
 
void CacheRegisterRelcacheCallback (RelcacheCallbackFunction func, Datum arg)
 
void CallSyscacheCallbacks (int cacheid, uint32 hashvalue)
 
void LogLogicalInvalidations (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 745 of file inval.c.

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

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

Referenced by apply_handle_commit_internal(), AtStart_Cache(), ConditionalLockRelation(), ConditionalLockRelationOid(), delay_execution_planner(), InitializeSessionUserId(), LockDatabaseObject(), LockRelation(), LockRelationOid(), LockSharedObject(), LogicalRepApplyLoop(), 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:427
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:53
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863

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

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

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

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

1339 {
1340  Oid databaseId;
1341 
1343 
1344  if (IsSharedRelation(catalogId))
1345  databaseId = InvalidOid;
1346  else
1347  databaseId = MyDatabaseId;
1348 
1349  RegisterCatalogInvalidation(databaseId, catalogId);
1350 }
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:244
Oid MyDatabaseId
Definition: globals.c:88
static void PrepareInvalidationState(void)
Definition: inval.c:794
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 1206 of file inval.c.

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

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

1422 {
1423  HeapTuple tup;
1424 
1426 
1427  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1428  if (!HeapTupleIsValid(tup))
1429  elog(ERROR, "cache lookup failed for relation %u", relid);
1431  ReleaseSysCache(tup);
1432 }
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1398
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1198
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1150
@ RELOID
Definition: syscache.h:87

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

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

◆ CacheInvalidateRelcacheByTuple()

void CacheInvalidateRelcacheByTuple ( HeapTuple  classTuple)

Definition at line 1398 of file inval.c.

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

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

1492 {
1494 
1495  msg.rm.id = SHAREDINVALRELMAP_ID;
1496  msg.rm.dbId = databaseId;
1497  /* check AddCatcacheInvalidationMessage() for an explanation */
1498  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1499 
1500  SendSharedInvalidMessages(&msg, 1);
1501 }
#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 ( RelFileNodeBackend  rnode)

Definition at line 1461 of file inval.c.

1462 {
1464 
1465  msg.sm.id = SHAREDINVALSMGR_ID;
1466  msg.sm.backend_hi = rnode.backend >> 16;
1467  msg.sm.backend_lo = rnode.backend & 0xffff;
1468  msg.sm.rnode = rnode.node;
1469  /* check AddCatcacheInvalidationMessage() for an explanation */
1470  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1471 
1472  SendSharedInvalidMessages(&msg, 1);
1473 }
#define SHAREDINVALSMGR_ID
Definition: sinval.h:85
BackendId backend
Definition: relfilenode.h:75
RelFileNode node
Definition: relfilenode.h:74
uint16 backend_lo
Definition: sinval.h:92
RelFileNode rnode
Definition: sinval.h:93
SharedInvalSmgrMsg sm
Definition: sinval.h:119

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

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

◆ CacheRegisterRelcacheCallback()

void CacheRegisterRelcacheCallback ( RelcacheCallbackFunction  func,
Datum  arg 
)

Definition at line 1560 of file inval.c.

1562 {
1564  elog(FATAL, "out of relcache_callback_list slots");
1565 
1568 
1570 }
#define FATAL
Definition: elog.h:35
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(), InitializeRelfilenodeMap(), InitPlanCache(), logicalrep_partmap_init(), logicalrep_relmap_init(), and lookup_type_cache().

◆ CacheRegisterSyscacheCallback()

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

Definition at line 1518 of file inval.c.

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

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

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

◆ CallSyscacheCallbacks()

void CallSyscacheCallbacks ( int  cacheid,
uint32  hashvalue 
)

Definition at line 1579 of file inval.c.

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

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

Referenced by CatalogCacheFlushCatalog(), and LocalExecuteInvalidationMessage().

◆ CommandEndInvalidationMessages()

void CommandEndInvalidationMessages ( void  )

Definition at line 1172 of file inval.c.

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

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

Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().

◆ InvalidateSystemCaches()

void InvalidateSystemCaches ( void  )

◆ InvalidateSystemCachesExtended()

void InvalidateSystemCachesExtended ( bool  debug_discard)

Definition at line 707 of file inval.c.

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

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

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

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

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

◆ LogLogicalInvalidations()

void LogLogicalInvalidations ( void  )

Definition at line 1606 of file inval.c.

1607 {
1608  xl_xact_invals xlrec;
1609  InvalidationMsgsGroup *group;
1610  int nmsgs;
1611 
1612  /* Quick exit if we haven't done anything with invalidation messages. */
1613  if (transInvalInfo == NULL)
1614  return;
1615 
1617  nmsgs = NumMessagesInGroup(group);
1618 
1619  if (nmsgs > 0)
1620  {
1621  /* prepare record */
1622  memset(&xlrec, 0, MinSizeOfXactInvals);
1623  xlrec.nmsgs = nmsgs;
1624 
1625  /* perform insertion */
1626  XLogBeginInsert();
1627  XLogRegisterData((char *) (&xlrec), MinSizeOfXactInvals);
1629  XLogRegisterData((char *) msgs,
1630  n * sizeof(SharedInvalidationMessage)));
1632  XLogRegisterData((char *) msgs,
1633  n * sizeof(SharedInvalidationMessage)));
1634  XLogInsert(RM_XACT_ID, XLOG_XACT_INVALIDATIONS);
1635  }
1636 }
#define NumMessagesInGroup(group)
Definition: inval.c:197
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
Definition: inval.c:372
int nmsgs
Definition: xact.h:254
#define MinSizeOfXactInvals
Definition: xact.h:257
#define XLOG_XACT_INVALIDATIONS
Definition: xact.h:154
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:429
void XLogBeginInsert(void)
Definition: xloginsert.c:136
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:337

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:1027

References AtEOXact_Inval().

Referenced by PrepareTransaction().

◆ PrepareInvalidationState()

static void PrepareInvalidationState ( void  )
static

Definition at line 794 of file inval.c.

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

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(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
970  (RelcacheInitFileInval ? " and relcache file invalidation" : ""));
971 
972  if (RelcacheInitFileInval)
973  {
974  elog(trace_recovery(DEBUG4), "removing relcache init files for database %u",
975  dbid);
976 
977  /*
978  * RelationCacheInitFilePreInvalidate, when the invalidation message
979  * is for a specific database, requires DatabasePath to be set, but we
980  * should not use SetDatabasePath during recovery, since it is
981  * intended to be used only once by normal backends. Hence, a quick
982  * hack: set DatabasePath directly then unset after use.
983  */
984  if (OidIsValid(dbid))
985  DatabasePath = GetDatabasePath(dbid, tsid);
986 
988 
989  if (OidIsValid(dbid))
990  {
992  DatabasePath = NULL;
993  }
994  }
995 
996  SendSharedInvalidMessages(msgs, nmsgs);
997 
998  if (RelcacheInitFileInval)
1000 }
int trace_recovery(int trace_level)
Definition: elog.c:3425
#define DEBUG4
Definition: elog.h:21
char * DatabasePath
Definition: globals.c:96
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110

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

Referenced by standby_redo(), and xact_redo_commit().

◆ ProcessInvalidationMessages()

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

Definition at line 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:6488
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:813

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 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:54

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