PostgreSQL Source Code  git master
sinval.h File Reference
#include <signal.h>
#include "storage/relfilenode.h"
Include dependency graph for sinval.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SharedInvalCatcacheMsg
 
struct  SharedInvalCatalogMsg
 
struct  SharedInvalRelcacheMsg
 
struct  SharedInvalSmgrMsg
 
struct  SharedInvalRelmapMsg
 
struct  SharedInvalSnapshotMsg
 
union  SharedInvalidationMessage
 

Macros

#define SHAREDINVALCATALOG_ID   (-1)
 
#define SHAREDINVALRELCACHE_ID   (-2)
 
#define SHAREDINVALSMGR_ID   (-3)
 
#define SHAREDINVALRELMAP_ID   (-4)
 
#define SHAREDINVALSNAPSHOT_ID   (-5)
 

Functions

void SendSharedInvalidMessages (const SharedInvalidationMessage *msgs, int n)
 
void ReceiveSharedInvalidMessages (void(*invalFunction)(SharedInvalidationMessage *msg), void(*resetFunction)(void))
 
void HandleCatchupInterrupt (void)
 
void ProcessCatchupInterrupt (void)
 
int xactGetCommittedInvalidationMessages (SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
 
void ProcessCommittedInvalidationMessages (SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
 
void LocalExecuteInvalidationMessage (SharedInvalidationMessage *msg)
 

Variables

uint64 SharedInvalidMessageCounter
 
volatile sig_atomic_t catchupInterruptPending
 

Macro Definition Documentation

◆ SHAREDINVALCATALOG_ID

#define SHAREDINVALCATALOG_ID   (-1)

◆ SHAREDINVALRELCACHE_ID

#define SHAREDINVALRELCACHE_ID   (-2)

◆ SHAREDINVALRELMAP_ID

#define SHAREDINVALRELMAP_ID   (-4)

◆ SHAREDINVALSMGR_ID

#define SHAREDINVALSMGR_ID   (-3)

◆ SHAREDINVALSNAPSHOT_ID

#define SHAREDINVALSNAPSHOT_ID   (-5)

Function Documentation

◆ HandleCatchupInterrupt()

void HandleCatchupInterrupt ( void  )

Definition at line 156 of file sinval.c.

References catchupInterruptPending, MyLatch, and SetLatch().

Referenced by procsignal_sigusr1_handler().

157 {
158  /*
159  * Note: this is called by a SIGNAL HANDLER. You must be very wary what
160  * you do here.
161  */
162 
164 
165  /* make sure the event is processed in due course */
166  SetLatch(MyLatch);
167 }
void SetLatch(Latch *latch)
Definition: latch.c:567
struct Latch * MyLatch
Definition: globals.c:57
volatile sig_atomic_t catchupInterruptPending
Definition: sinval.c:41

◆ LocalExecuteInvalidationMessage()

void LocalExecuteInvalidationMessage ( SharedInvalidationMessage msg)

Definition at line 600 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, 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().

601 {
602  if (msg->id >= 0)
603  {
604  if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
605  {
607 
608  SysCacheInvalidate(msg->cc.id, msg->cc.hashValue);
609 
610  CallSyscacheCallbacks(msg->cc.id, msg->cc.hashValue);
611  }
612  }
613  else if (msg->id == SHAREDINVALCATALOG_ID)
614  {
615  if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
616  {
618 
620 
621  /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
622  }
623  }
624  else if (msg->id == SHAREDINVALRELCACHE_ID)
625  {
626  if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
627  {
628  int i;
629 
630  if (msg->rc.relId == InvalidOid)
632  else
634 
635  for (i = 0; i < relcache_callback_count; i++)
636  {
637  struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
638 
639  ccitem->function(ccitem->arg, msg->rc.relId);
640  }
641  }
642  }
643  else if (msg->id == SHAREDINVALSMGR_ID)
644  {
645  /*
646  * We could have smgr entries for relations of other databases, so no
647  * short-circuit test is possible here.
648  */
649  RelFileNodeBackend rnode;
650 
651  rnode.node = msg->sm.rnode;
652  rnode.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
653  smgrclosenode(rnode);
654  }
655  else if (msg->id == SHAREDINVALRELMAP_ID)
656  {
657  /* We only care about our own database and shared catalogs */
658  if (msg->rm.dbId == InvalidOid)
659  RelationMapInvalidate(true);
660  else if (msg->rm.dbId == MyDatabaseId)
661  RelationMapInvalidate(false);
662  }
663  else if (msg->id == SHAREDINVALSNAPSHOT_ID)
664  {
665  /* We only care about our own database and shared catalogs */
666  if (msg->sn.dbId == InvalidOid)
668  else if (msg->sn.dbId == MyDatabaseId)
670  }
671  else
672  elog(FATAL, "unrecognized SI message ID: %d", msg->id);
673 }
SharedInvalSnapshotMsg sn
Definition: sinval.h:121
SharedInvalRelcacheMsg rc
Definition: sinval.h:118
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
static int relcache_callback_count
Definition: inval.c:259
RelcacheCallbackFunction function
Definition: inval.c:255
void RelationMapInvalidate(bool shared)
Definition: relmapper.c:403
#define FATAL
Definition: elog.h:49
#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:456
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1559
Oid MyDatabaseId
Definition: globals.c:88
#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:1460
void CatalogCacheFlushCatalog(Oid catId)
Definition: catcache.c:719
BackendId backend
Definition: relfilenode.h:75
void RelationCacheInvalidateEntry(Oid relationId)
Definition: relcache.c:2797
uint16 backend_lo
Definition: sinval.h:92
#define SHAREDINVALCATALOG_ID
Definition: sinval.h:67
#define elog(elevel,...)
Definition: elog.h:232
void RelationCacheInvalidate(void)
Definition: relcache.c:2840
int i
RelFileNode rnode
Definition: sinval.h:93
#define SHAREDINVALSMGR_ID
Definition: sinval.h:85

◆ ProcessCatchupInterrupt()

void ProcessCatchupInterrupt ( void  )

Definition at line 176 of file sinval.c.

References AcceptInvalidationMessages(), catchupInterruptPending, CommitTransactionCommand(), DEBUG4, elog, IsTransactionOrTransactionBlock(), and StartTransactionCommand().

Referenced by HandleAutoVacLauncherInterrupts(), and ProcessClientReadInterrupt().

177 {
179  {
180  /*
181  * What we need to do here is cause ReceiveSharedInvalidMessages() to
182  * run, which will do the necessary work and also reset the
183  * catchupInterruptPending flag. If we are inside a transaction we
184  * can just call AcceptInvalidationMessages() to do this. If we
185  * aren't, we start and immediately end a transaction; the call to
186  * AcceptInvalidationMessages() happens down inside transaction start.
187  *
188  * It is awfully tempting to just call AcceptInvalidationMessages()
189  * without the rest of the xact start/stop overhead, and I think that
190  * would actually work in the normal case; but I am not sure that
191  * things would clean up nicely if we got an error partway through.
192  */
194  {
195  elog(DEBUG4, "ProcessCatchupEvent inside transaction");
197  }
198  else
199  {
200  elog(DEBUG4, "ProcessCatchupEvent outside transaction");
203  }
204  }
205 }
void AcceptInvalidationMessages(void)
Definition: inval.c:725
void CommitTransactionCommand(void)
Definition: xact.c:2949
bool IsTransactionOrTransactionBlock(void)
Definition: xact.c:4711
#define DEBUG4
Definition: elog.h:22
void StartTransactionCommand(void)
Definition: xact.c:2848
#define elog(elevel,...)
Definition: elog.h:232
volatile sig_atomic_t catchupInterruptPending
Definition: sinval.c:41

◆ ProcessCommittedInvalidationMessages()

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

Definition at line 942 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().

945 {
946  if (nmsgs <= 0)
947  return;
948 
949  elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
950  (RelcacheInitFileInval ? " and relcache file invalidation" : ""));
951 
952  if (RelcacheInitFileInval)
953  {
954  elog(trace_recovery(DEBUG4), "removing relcache init files for database %u",
955  dbid);
956 
957  /*
958  * RelationCacheInitFilePreInvalidate, when the invalidation message
959  * is for a specific database, requires DatabasePath to be set, but we
960  * should not use SetDatabasePath during recovery, since it is
961  * intended to be used only once by normal backends. Hence, a quick
962  * hack: set DatabasePath directly then unset after use.
963  */
964  if (OidIsValid(dbid))
965  DatabasePath = GetDatabasePath(dbid, tsid);
966 
968 
969  if (OidIsValid(dbid))
970  {
972  DatabasePath = NULL;
973  }
974  }
975 
976  SendSharedInvalidMessages(msgs, nmsgs);
977 
978  if (RelcacheInitFileInval)
980 }
#define DEBUG4
Definition: elog.h:22
#define OidIsValid(objectId)
Definition: c.h:710
int trace_recovery(int trace_level)
Definition: elog.c:3603
void pfree(void *pointer)
Definition: mcxt.c:1169
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110
void RelationCacheInitFilePostInvalidate(void)
Definition: relcache.c:6465
char * DatabasePath
Definition: globals.c:96
void RelationCacheInitFilePreInvalidate(void)
Definition: relcache.c:6440
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
Definition: sinval.c:49
#define elog(elevel,...)
Definition: elog.h:232

◆ ReceiveSharedInvalidMessages()

void ReceiveSharedInvalidMessages ( void(*)(SharedInvalidationMessage *msg)  invalFunction,
void(*)(void)  resetFunction 
)

Definition at line 71 of file sinval.c.

References catchupInterruptPending, DEBUG4, elog, MAXINVALMSGS, SharedInvalidMessageCounter, SICleanupQueue(), and SIGetDataEntries().

Referenced by AcceptInvalidationMessages().

73 {
74 #define MAXINVALMSGS 32
75  static SharedInvalidationMessage messages[MAXINVALMSGS];
76 
77  /*
78  * We use volatile here to prevent bugs if a compiler doesn't realize that
79  * recursion is a possibility ...
80  */
81  static volatile int nextmsg = 0;
82  static volatile int nummsgs = 0;
83 
84  /* Deal with any messages still pending from an outer recursion */
85  while (nextmsg < nummsgs)
86  {
87  SharedInvalidationMessage msg = messages[nextmsg++];
88 
90  invalFunction(&msg);
91  }
92 
93  do
94  {
95  int getResult;
96 
97  nextmsg = nummsgs = 0;
98 
99  /* Try to get some more messages */
100  getResult = SIGetDataEntries(messages, MAXINVALMSGS);
101 
102  if (getResult < 0)
103  {
104  /* got a reset message */
105  elog(DEBUG4, "cache state reset");
107  resetFunction();
108  break; /* nothing more to do */
109  }
110 
111  /* Process them, being wary that a recursive call might eat some */
112  nextmsg = 0;
113  nummsgs = getResult;
114 
115  while (nextmsg < nummsgs)
116  {
117  SharedInvalidationMessage msg = messages[nextmsg++];
118 
120  invalFunction(&msg);
121  }
122 
123  /*
124  * We only need to loop if the last SIGetDataEntries call (which might
125  * have been within a recursive call) returned a full buffer.
126  */
127  } while (nummsgs == MAXINVALMSGS);
128 
129  /*
130  * We are now caught up. If we received a catchup signal, reset that
131  * flag, and call SICleanupQueue(). This is not so much because we need
132  * to flush dead messages right now, as that we want to pass on the
133  * catchup signal to the next slowest backend. "Daisy chaining" the
134  * catchup signal this way avoids creating spikes in system load for what
135  * should be just a background maintenance activity.
136  */
138  {
139  catchupInterruptPending = false;
140  elog(DEBUG4, "sinval catchup complete, cleaning queue");
141  SICleanupQueue(false, 0);
142  }
143 }
#define DEBUG4
Definition: elog.h:22
int SIGetDataEntries(SharedInvalidationMessage *data, int datasize)
Definition: sinvaladt.c:536
#define MAXINVALMSGS
void SICleanupQueue(bool callerHasWriteLock, int minFree)
Definition: sinvaladt.c:640
uint64 SharedInvalidMessageCounter
Definition: sinval.c:26
#define elog(elevel,...)
Definition: elog.h:232
volatile sig_atomic_t catchupInterruptPending
Definition: sinval.c:41

◆ SendSharedInvalidMessages()

void SendSharedInvalidMessages ( const SharedInvalidationMessage msgs,
int  n 
)

Definition at line 49 of file sinval.c.

References SIInsertDataEntries().

Referenced by AtEOXact_Inval(), CacheInvalidateRelmap(), CacheInvalidateSmgr(), FinishPreparedTransaction(), and ProcessCommittedInvalidationMessages().

50 {
51  SIInsertDataEntries(msgs, n);
52 }
void SIInsertDataEntries(const SharedInvalidationMessage *data, int n)
Definition: sinvaladt.c:433

◆ xactGetCommittedInvalidationMessages()

int xactGetCommittedInvalidationMessages ( SharedInvalidationMessage **  msgs,
bool RelcacheInitFileInval 
)

Definition at line 863 of file inval.c.

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

Referenced by RecordTransactionCommit(), and StartPrepare().

865 {
866  SharedInvalidationMessage *msgarray;
867  int nummsgs;
868  int nmsgs;
869 
870  /* Quick exit if we haven't done anything with invalidation messages. */
871  if (transInvalInfo == NULL)
872  {
873  *RelcacheInitFileInval = false;
874  *msgs = NULL;
875  return 0;
876  }
877 
878  /* Must be at top of stack */
880 
881  /*
882  * Relcache init file invalidation requires processing both before and
883  * after we send the SI messages. However, we need not do anything unless
884  * we committed.
885  */
886  *RelcacheInitFileInval = transInvalInfo->RelcacheInitFileInval;
887 
888  /*
889  * Collect all the pending messages into a single contiguous array of
890  * invalidation messages, to simplify what needs to happen while building
891  * the commit WAL message. Maintain the order that they would be
892  * processed in by AtEOXact_Inval(), to ensure emulated behaviour in redo
893  * is as similar as possible to original. We want the same bugs, if any,
894  * not new ones.
895  */
898 
899  *msgs = msgarray = (SharedInvalidationMessage *)
901  nummsgs * sizeof(SharedInvalidationMessage));
902 
903  nmsgs = 0;
905  CatCacheMsgs,
906  (memcpy(msgarray + nmsgs,
907  msgs,
908  n * sizeof(SharedInvalidationMessage)),
909  nmsgs += n));
911  CatCacheMsgs,
912  (memcpy(msgarray + nmsgs,
913  msgs,
914  n * sizeof(SharedInvalidationMessage)),
915  nmsgs += n));
917  RelCacheMsgs,
918  (memcpy(msgarray + nmsgs,
919  msgs,
920  n * sizeof(SharedInvalidationMessage)),
921  nmsgs += n));
923  RelCacheMsgs,
924  (memcpy(msgarray + nmsgs,
925  msgs,
926  n * sizeof(SharedInvalidationMessage)),
927  nmsgs += n));
928  Assert(nmsgs == nummsgs);
929 
930  return nmsgs;
931 }
#define RelCacheMsgs
Definition: inval.c:148
#define CatCacheMsgs
Definition: inval.c:147
MemoryContext CurTransactionContext
Definition: mcxt.c:54
struct TransInvalidationInfo * parent
Definition: inval.c:208
static TransInvalidationInfo * transInvalInfo
Definition: inval.c:223
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
Definition: inval.c:358
bool RelcacheInitFileInval
Definition: inval.c:220
#define NumMessagesInGroup(group)
Definition: inval.c:183
#define Assert(condition)
Definition: c.h:804
InvalidationMsgsGroup PriorCmdInvalidMsgs
Definition: inval.c:217
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
InvalidationMsgsGroup CurrentCmdInvalidMsgs
Definition: inval.c:214

Variable Documentation

◆ catchupInterruptPending

volatile sig_atomic_t catchupInterruptPending

◆ SharedInvalidMessageCounter

uint64 SharedInvalidMessageCounter