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

Go to the source code of this file.

Data Structures

struct  InvalidationChunk
 
struct  InvalidationListHeader
 
struct  TransInvalidationInfo
 
struct  SYSCACHECALLBACK
 
struct  RELCACHECALLBACK
 

Macros

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

Typedefs

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

Functions

static void AddInvalidationMessage (InvalidationChunk **listHdr, SharedInvalidationMessage *msg)
 
static void AppendInvalidationMessageList (InvalidationChunk **destHdr, InvalidationChunk **srcHdr)
 
static void AddCatcacheInvalidationMessage (InvalidationListHeader *hdr, int id, uint32 hashValue, Oid dbId)
 
static void AddCatalogInvalidationMessage (InvalidationListHeader *hdr, Oid dbId, Oid catId)
 
static void AddRelcacheInvalidationMessage (InvalidationListHeader *hdr, Oid dbId, Oid relId)
 
static void AddSnapshotInvalidationMessage (InvalidationListHeader *hdr, Oid dbId, Oid relId)
 
static void AppendInvalidationMessages (InvalidationListHeader *dest, InvalidationListHeader *src)
 
static void ProcessInvalidationMessages (InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
 
static void ProcessInvalidationMessagesMulti (InvalidationListHeader *hdr, void(*func)(const SharedInvalidationMessage *msgs, int n))
 
static void RegisterCatcacheInvalidation (int cacheId, uint32 hashValue, Oid dbId)
 
static void RegisterCatalogInvalidation (Oid dbId, Oid catId)
 
static void RegisterRelcacheInvalidation (Oid dbId, Oid relId)
 
static void RegisterSnapshotInvalidation (Oid dbId, Oid relId)
 
void LocalExecuteInvalidationMessage (SharedInvalidationMessage *msg)
 
void InvalidateSystemCaches (void)
 
void AcceptInvalidationMessages (void)
 
static void PrepareInvalidationState (void)
 
void PostPrepare_Inval (void)
 
static void MakeSharedInvalidMessagesArray (const SharedInvalidationMessage *msgs, int n)
 
int xactGetCommittedInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
void ProcessCommittedInvalidationMessages (SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
 
void AtEOXact_Inval (bool isCommit)
 
void AtEOSubXact_Inval (bool isCommit)
 
void CommandEndInvalidationMessages (void)
 
void CacheInvalidateHeapTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple)
 
void CacheInvalidateCatalog (Oid catalogId)
 
void CacheInvalidateRelcache (Relation relation)
 
void CacheInvalidateRelcacheAll (void)
 
void CacheInvalidateRelcacheByTuple (HeapTuple classTuple)
 
void CacheInvalidateRelcacheByRelid (Oid relid)
 
void CacheInvalidateSmgr (RelFileNodeBackend rnode)
 
void CacheInvalidateRelmap (Oid databaseId)
 
void CacheRegisterSyscacheCallback (int cacheid, SyscacheCallbackFunction func, Datum arg)
 
void CacheRegisterRelcacheCallback (RelcacheCallbackFunction func, Datum arg)
 
void CallSyscacheCallbacks (int cacheid, uint32 hashvalue)
 

Variables

static TransInvalidationInfotransInvalInfo = NULL
 
static SharedInvalidationMessageSharedInvalidMessagesArray
 
static int numSharedInvalidMessagesArray
 
static int maxSharedInvalidMessagesArray
 
static struct SYSCACHECALLBACK syscache_callback_list [MAX_SYSCACHE_CALLBACKS]
 
static int16 syscache_callback_links [SysCacheSize]
 
static int syscache_callback_count = 0
 
static struct RELCACHECALLBACK relcache_callback_list [MAX_RELCACHE_CALLBACKS]
 
static int relcache_callback_count = 0
 

Macro Definition Documentation

◆ FIRSTCHUNKSIZE

#define FIRSTCHUNKSIZE   32

◆ MAX_RELCACHE_CALLBACKS

#define MAX_RELCACHE_CALLBACKS   10

Definition at line 191 of file inval.c.

Referenced by CacheRegisterRelcacheCallback().

◆ MAX_SYSCACHE_CALLBACKS

#define MAX_SYSCACHE_CALLBACKS   64

Definition at line 190 of file inval.c.

Referenced by CacheRegisterSyscacheCallback().

◆ ProcessMessageList

#define ProcessMessageList (   listHdr,
  codeFragment 
)
Value:
do { \
InvalidationChunk *_chunk; \
for (_chunk = (listHdr); _chunk != NULL; _chunk = _chunk->next) \
{ \
int _cindex; \
for (_cindex = 0; _cindex < _chunk->nitems; _cindex++) \
{ \
SharedInvalidationMessage *msg = &_chunk->msgs[_cindex]; \
codeFragment; \
} \
} \
} while (0)

Definition at line 295 of file inval.c.

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

◆ ProcessMessageListMulti

#define ProcessMessageListMulti (   listHdr,
  codeFragment 
)
Value:
do { \
InvalidationChunk *_chunk; \
for (_chunk = (listHdr); _chunk != NULL; _chunk = _chunk->next) \
{ \
SharedInvalidationMessage *msgs = _chunk->msgs; \
int n = _chunk->nitems; \
codeFragment; \
} \
} while (0)

Definition at line 315 of file inval.c.

Referenced by ProcessInvalidationMessagesMulti().

Typedef Documentation

◆ InvalidationChunk

◆ InvalidationListHeader

◆ TransInvalidationInfo

Function Documentation

◆ AcceptInvalidationMessages()

void AcceptInvalidationMessages ( void  )

Definition at line 681 of file inval.c.

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

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

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

◆ AddCatalogInvalidationMessage()

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

Definition at line 367 of file inval.c.

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

Referenced by RegisterCatalogInvalidation().

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

◆ AddCatcacheInvalidationMessage()

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

Definition at line 339 of file inval.c.

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

Referenced by RegisterCatcacheInvalidation().

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

◆ AddInvalidationMessage()

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

Definition at line 229 of file inval.c.

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

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

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

◆ AddRelcacheInvalidationMessage()

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

Definition at line 385 of file inval.c.

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

Referenced by RegisterRelcacheInvalidation().

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

◆ AddSnapshotInvalidationMessage()

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

Definition at line 415 of file inval.c.

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

Referenced by RegisterSnapshotInvalidation().

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

◆ AppendInvalidationMessageList()

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

Definition at line 271 of file inval.c.

References InvalidationChunk::next.

Referenced by AppendInvalidationMessages().

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

◆ AppendInvalidationMessages()

static void AppendInvalidationMessages ( InvalidationListHeader dest,
InvalidationListHeader src 
)
static

Definition at line 442 of file inval.c.

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

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

444 {
447 }
InvalidationChunk * cclist
Definition: inval.c:134
InvalidationChunk * rclist
Definition: inval.c:135
static void AppendInvalidationMessageList(InvalidationChunk **destHdr, InvalidationChunk **srcHdr)
Definition: inval.c:271

◆ AtEOSubXact_Inval()

void AtEOSubXact_Inval ( bool  isCommit)

Definition at line 1008 of file inval.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

◆ AtEOXact_Inval()

void AtEOXact_Inval ( bool  isCommit)

Definition at line 949 of file inval.c.

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

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

950 {
951  /* Quick exit if no messages */
952  if (transInvalInfo == NULL)
953  return;
954 
955  /* Must be at top of stack */
957 
958  if (isCommit)
959  {
960  /*
961  * Relcache init file invalidation requires processing both before and
962  * after we send the SI messages. However, we need not do anything
963  * unless we committed.
964  */
967 
970 
973 
976  }
977  else
978  {
981  }
982 
983  /* Need not free anything explicitly */
984  transInvalInfo = NULL;
987 }
static void AppendInvalidationMessages(InvalidationListHeader *dest, InvalidationListHeader *src)
Definition: inval.c:442
static SharedInvalidationMessage * SharedInvalidMessagesArray
Definition: inval.c:175
InvalidationListHeader PriorCmdInvalidMsgs
Definition: inval.c:167
struct TransInvalidationInfo * parent
Definition: inval.c:158
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:173
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:164
static int numSharedInvalidMessagesArray
Definition: inval.c:176
static void ProcessInvalidationMessagesMulti(InvalidationListHeader *hdr, void(*func)(const SharedInvalidationMessage *msgs, int n))
Definition: inval.c:468
bool RelcacheInitFileInval
Definition: inval.c:170
static void ProcessInvalidationMessages(InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:456
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6006
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:5981
#define Assert(condition)
Definition: c.h:732
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:556

◆ CacheInvalidateCatalog()

void CacheInvalidateCatalog ( Oid  catalogId)

Definition at line 1246 of file inval.c.

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

Referenced by finish_heap_swap().

1247 {
1248  Oid databaseId;
1249 
1251 
1252  if (IsSharedRelation(catalogId))
1253  databaseId = InvalidOid;
1254  else
1255  databaseId = MyDatabaseId;
1256 
1257  RegisterCatalogInvalidation(databaseId, catalogId);
1258 }
unsigned int Oid
Definition: postgres_ext.h:31
static void PrepareInvalidationState(void)
Definition: inval.c:732
Oid MyDatabaseId
Definition: globals.c:85
static void RegisterCatalogInvalidation(Oid dbId, Oid catId)
Definition: inval.c:500
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:240
#define InvalidOid
Definition: postgres_ext.h:36

◆ CacheInvalidateHeapTuple()

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

Definition at line 1114 of file inval.c.

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

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

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

◆ CacheInvalidateRelcache()

void CacheInvalidateRelcache ( Relation  relation)

Definition at line 1270 of file inval.c.

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

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

1271 {
1272  Oid databaseId;
1273  Oid relationId;
1274 
1276 
1277  relationId = RelationGetRelid(relation);
1278  if (relation->rd_rel->relisshared)
1279  databaseId = InvalidOid;
1280  else
1281  databaseId = MyDatabaseId;
1282 
1283  RegisterRelcacheInvalidation(databaseId, relationId);
1284 }
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
static void PrepareInvalidationState(void)
Definition: inval.c:732
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:512
#define RelationGetRelid(relation)
Definition: rel.h:416

◆ CacheInvalidateRelcacheAll()

void CacheInvalidateRelcacheAll ( void  )

Definition at line 1294 of file inval.c.

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

Referenced by AlterPublicationOptions().

1295 {
1297 
1299 }
static void PrepareInvalidationState(void)
Definition: inval.c:732
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:512

◆ CacheInvalidateRelcacheByRelid()

void CacheInvalidateRelcacheByRelid ( Oid  relid)

Definition at line 1329 of file inval.c.

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

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

1330 {
1331  HeapTuple tup;
1332 
1334 
1335  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1336  if (!HeapTupleIsValid(tup))
1337  elog(ERROR, "cache lookup failed for relation %u", relid);
1339  ReleaseSysCache(tup);
1340 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static void PrepareInvalidationState(void)
Definition: inval.c:732
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1306

◆ CacheInvalidateRelcacheByTuple()

void CacheInvalidateRelcacheByTuple ( HeapTuple  classTuple)

Definition at line 1306 of file inval.c.

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

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

1307 {
1308  Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple);
1309  Oid databaseId;
1310  Oid relationId;
1311 
1313 
1314  relationId = classtup->oid;
1315  if (classtup->relisshared)
1316  databaseId = InvalidOid;
1317  else
1318  databaseId = MyDatabaseId;
1319  RegisterRelcacheInvalidation(databaseId, relationId);
1320 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
unsigned int Oid
Definition: postgres_ext.h:31
static void PrepareInvalidationState(void)
Definition: inval.c:732
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
static void RegisterRelcacheInvalidation(Oid dbId, Oid relId)
Definition: inval.c:512
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150

◆ CacheInvalidateRelmap()

void CacheInvalidateRelmap ( Oid  databaseId)

Definition at line 1399 of file inval.c.

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

Referenced by write_relmap_file().

1400 {
1402 
1403  msg.rm.id = SHAREDINVALRELMAP_ID;
1404  msg.rm.dbId = databaseId;
1405  /* check AddCatcacheInvalidationMessage() for an explanation */
1406  VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
1407 
1408  SendSharedInvalidMessages(&msg, 1);
1409 }
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
SharedInvalRelmapMsg rm
Definition: sinval.h:120
#define SHAREDINVALRELMAP_ID
Definition: sinval.h:96
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49

◆ CacheInvalidateSmgr()

void CacheInvalidateSmgr ( RelFileNodeBackend  rnode)

Definition at line 1369 of file inval.c.

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

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

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

◆ CacheRegisterRelcacheCallback()

void CacheRegisterRelcacheCallback ( RelcacheCallbackFunction  func,
Datum  arg 
)

Definition at line 1468 of file inval.c.

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

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

1470 {
1472  elog(FATAL, "out of relcache_callback_list slots");
1473 
1476 
1478 }
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
#define MAX_RELCACHE_CALLBACKS
Definition: inval.c:191
static int relcache_callback_count
Definition: inval.c:211
RelcacheCallbackFunction function
Definition: inval.c:207
#define FATAL
Definition: elog.h:52
#define elog(elevel,...)
Definition: elog.h:226
void * arg

◆ CacheRegisterSyscacheCallback()

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

Definition at line 1426 of file inval.c.

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

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

1429 {
1430  if (cacheid < 0 || cacheid >= SysCacheSize)
1431  elog(FATAL, "invalid cache ID: %d", cacheid);
1433  elog(FATAL, "out of syscache_callback_list slots");
1434 
1435  if (syscache_callback_links[cacheid] == 0)
1436  {
1437  /* first callback for this cache */
1439  }
1440  else
1441  {
1442  /* add to end of chain, so that older callbacks are called first */
1443  int i = syscache_callback_links[cacheid] - 1;
1444 
1445  while (syscache_callback_list[i].link > 0)
1446  i = syscache_callback_list[i].link - 1;
1448  }
1449 
1454 
1456 }
int16 link
Definition: inval.c:196
#define SysCacheSize
Definition: syscache.h:113
#define FATAL
Definition: elog.h:52
#define MAX_SYSCACHE_CALLBACKS
Definition: inval.c:190
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
static int syscache_callback_count
Definition: inval.c:203
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:201
#define elog(elevel,...)
Definition: elog.h:226
int i
void * arg
SyscacheCallbackFunction function
Definition: inval.c:197

◆ CallSyscacheCallbacks()

void CallSyscacheCallbacks ( int  cacheid,
uint32  hashvalue 
)

Definition at line 1487 of file inval.c.

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

Referenced by CatalogCacheFlushCatalog(), and LocalExecuteInvalidationMessage().

1488 {
1489  int i;
1490 
1491  if (cacheid < 0 || cacheid >= SysCacheSize)
1492  elog(ERROR, "invalid cache ID: %d", cacheid);
1493 
1494  i = syscache_callback_links[cacheid] - 1;
1495  while (i >= 0)
1496  {
1497  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
1498 
1499  Assert(ccitem->id == cacheid);
1500  ccitem->function(ccitem->arg, cacheid, hashvalue);
1501  i = ccitem->link - 1;
1502  }
1503 }
int16 link
Definition: inval.c:196
#define SysCacheSize
Definition: syscache.h:113
#define ERROR
Definition: elog.h:43
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
#define Assert(condition)
Definition: c.h:732
static int16 syscache_callback_links[SysCacheSize]
Definition: inval.c:201
#define elog(elevel,...)
Definition: elog.h:226
int i
SyscacheCallbackFunction function
Definition: inval.c:197

◆ CommandEndInvalidationMessages()

void CommandEndInvalidationMessages ( void  )

Definition at line 1085 of file inval.c.

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

Referenced by AtCCI_LocalCache(), and AtEOSubXact_Inval().

1086 {
1087  /*
1088  * You might think this shouldn't be called outside any transaction, but
1089  * bootstrap does it, and also ABORT issued when not in a transaction. So
1090  * just quietly return if no state to work on.
1091  */
1092  if (transInvalInfo == NULL)
1093  return;
1094 
1099 }
static void AppendInvalidationMessages(InvalidationListHeader *dest, InvalidationListHeader *src)
Definition: inval.c:442
InvalidationListHeader PriorCmdInvalidMsgs
Definition: inval.c:167
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:173
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:164
static void ProcessInvalidationMessages(InvalidationListHeader *hdr, void(*func)(SharedInvalidationMessage *msg))
Definition: inval.c:456
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
Definition: inval.c:556

◆ InvalidateSystemCaches()

void InvalidateSystemCaches ( void  )

Definition at line 643 of file inval.c.

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

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

644 {
645  int i;
646 
649  RelationCacheInvalidate(); /* gets smgr and relmap too */
650 
651  for (i = 0; i < syscache_callback_count; i++)
652  {
653  struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
654 
655  ccitem->function(ccitem->arg, ccitem->id, 0);
656  }
657 
658  for (i = 0; i < relcache_callback_count; i++)
659  {
660  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
661 
662  ccitem->function(ccitem->arg, InvalidOid);
663  }
664 }
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
static int relcache_callback_count
Definition: inval.c:211
RelcacheCallbackFunction function
Definition: inval.c:207
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:512
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
static int syscache_callback_count
Definition: inval.c:203
#define InvalidOid
Definition: postgres_ext.h:36
void ResetCatalogCaches(void)
Definition: catcache.c:689
void RelationCacheInvalidate(void)
Definition: relcache.c:2779
int i
SyscacheCallbackFunction function
Definition: inval.c:197

◆ LocalExecuteInvalidationMessage()

void LocalExecuteInvalidationMessage ( SharedInvalidationMessage msg)

Definition at line 556 of file inval.c.

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

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

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

◆ MakeSharedInvalidMessagesArray()

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

Definition at line 778 of file inval.c.

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

Referenced by xactGetCommittedInvalidationMessages().

779 {
780  /*
781  * Initialise array first time through in each commit
782  */
783  if (SharedInvalidMessagesArray == NULL)
784  {
787 
788  /*
789  * Although this is being palloc'd we don't actually free it directly.
790  * We're so close to EOXact that we now we're going to lose it anyhow.
791  */
793  * sizeof(SharedInvalidationMessage));
794  }
795 
797  {
800 
803  * sizeof(SharedInvalidationMessage));
804  }
805 
806  /*
807  * Append the next chunk onto the array
808  */
810  msgs, n * sizeof(SharedInvalidationMessage));
812 }
#define FIRSTCHUNKSIZE
static SharedInvalidationMessage * SharedInvalidMessagesArray
Definition: inval.c:175
static int numSharedInvalidMessagesArray
Definition: inval.c:176
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
static int maxSharedInvalidMessagesArray
Definition: inval.c:177
void * palloc(Size size)
Definition: mcxt.c:924

◆ PostPrepare_Inval()

void PostPrepare_Inval ( void  )

Definition at line 769 of file inval.c.

References AtEOXact_Inval().

Referenced by PrepareTransaction().

770 {
771  AtEOXact_Inval(false);
772 }
void AtEOXact_Inval(bool isCommit)
Definition: inval.c:949

◆ PrepareInvalidationState()

static void PrepareInvalidationState ( void  )
static

Definition at line 732 of file inval.c.

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

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

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

◆ ProcessCommittedInvalidationMessages()

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

Definition at line 884 of file inval.c.

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

Referenced by standby_redo(), and xact_redo_commit().

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

◆ ProcessInvalidationMessages()

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

Definition at line 456 of file inval.c.

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

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

458 {
459  ProcessMessageList(hdr->cclist, func(msg));
460  ProcessMessageList(hdr->rclist, func(msg));
461 }
#define ProcessMessageList(listHdr, codeFragment)
Definition: inval.c:295
InvalidationChunk * cclist
Definition: inval.c:134
InvalidationChunk * rclist
Definition: inval.c:135

◆ ProcessInvalidationMessagesMulti()

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

Definition at line 468 of file inval.c.

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

Referenced by AtEOXact_Inval(), and xactGetCommittedInvalidationMessages().

470 {
471  ProcessMessageListMulti(hdr->cclist, func(msgs, n));
472  ProcessMessageListMulti(hdr->rclist, func(msgs, n));
473 }
#define ProcessMessageListMulti(listHdr, codeFragment)
Definition: inval.c:315
InvalidationChunk * cclist
Definition: inval.c:134
InvalidationChunk * rclist
Definition: inval.c:135

◆ RegisterCatalogInvalidation()

static void RegisterCatalogInvalidation ( Oid  dbId,
Oid  catId 
)
static

Definition at line 500 of file inval.c.

References AddCatalogInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateCatalog().

501 {
503  dbId, catId);
504 }
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:173
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:164
static void AddCatalogInvalidationMessage(InvalidationListHeader *hdr, Oid dbId, Oid catId)
Definition: inval.c:367

◆ RegisterCatcacheInvalidation()

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

Definition at line 486 of file inval.c.

References AddCatcacheInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateHeapTuple().

489 {
491  cacheId, hashValue, dbId);
492 }
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:173
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:164
static void AddCatcacheInvalidationMessage(InvalidationListHeader *hdr, int id, uint32 hashValue, Oid dbId)
Definition: inval.c:339

◆ RegisterRelcacheInvalidation()

static void RegisterRelcacheInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 512 of file inval.c.

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

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

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

◆ RegisterSnapshotInvalidation()

static void RegisterSnapshotInvalidation ( Oid  dbId,
Oid  relId 
)
static

Definition at line 542 of file inval.c.

References AddSnapshotInvalidationMessage(), and TransInvalidationInfo::CurrentCmdInvalidMsgs.

Referenced by CacheInvalidateHeapTuple().

543 {
545  dbId, relId);
546 }
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:173
InvalidationListHeader CurrentCmdInvalidMsgs
Definition: inval.c:164
static void AddSnapshotInvalidationMessage(InvalidationListHeader *hdr, Oid dbId, Oid relId)
Definition: inval.c:415

◆ xactGetCommittedInvalidationMessages()

int xactGetCommittedInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool RelcacheInitFileInval 
)

Definition at line 828 of file inval.c.

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

Referenced by RecordTransactionCommit(), and StartPrepare().

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

Variable Documentation

◆ maxSharedInvalidMessagesArray

int maxSharedInvalidMessagesArray
static

Definition at line 177 of file inval.c.

Referenced by MakeSharedInvalidMessagesArray().

◆ numSharedInvalidMessagesArray

int numSharedInvalidMessagesArray
static

◆ relcache_callback_count

int relcache_callback_count = 0
static

◆ relcache_callback_list

◆ SharedInvalidMessagesArray

SharedInvalidationMessage* SharedInvalidMessagesArray
static

Definition at line 175 of file inval.c.

Referenced by xactGetCommittedInvalidationMessages().

◆ syscache_callback_count

int syscache_callback_count = 0
static

Definition at line 203 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and InvalidateSystemCaches().

◆ syscache_callback_links

int16 syscache_callback_links[SysCacheSize]
static

Definition at line 201 of file inval.c.

Referenced by CacheRegisterSyscacheCallback(), and CallSyscacheCallbacks().

◆ syscache_callback_list

◆ transInvalInfo

TransInvalidationInfo* transInvalInfo = NULL
static

Definition at line 173 of file inval.c.

Referenced by AtEOSubXact_Inval(), and PrepareInvalidationState().