1/*-------------------------------------------------------------------------
4 * POSTGRES cache invalidation dispatcher code.
6 * This is subtle stuff, so pay attention:
8 * When a tuple is updated or deleted, our standard visibility rules
9 * consider that it is *still valid* so long as we are in the same command,
10 * ie, until the next CommandCounterIncrement() or transaction commit.
11 * (See access/heap/heapam_visibility.c, and note that system catalogs are
12 * generally scanned under the most current snapshot available, rather than
13 * the transaction snapshot.) At the command boundary, the old tuple stops
14 * being valid and the new version, if any, becomes valid. Therefore,
15 * we cannot simply flush a tuple from the system caches during heap_update()
16 * or heap_delete(). The tuple is still good at that point; what's more,
17 * even if we did flush it, it might be reloaded into the caches by a later
18 * request in the same command. So the correct behavior is to keep a list
19 * of outdated (updated/deleted) tuples and then do the required cache
20 * flushes at the next command boundary. We must also keep track of
21 * inserted tuples so that we can flush "negative" cache entries that match
22 * the new tuples; again, that mustn't happen until end of command.
24 * Once we have finished the command, we still need to remember inserted
25 * tuples (including new versions of updated tuples), so that we can flush
26 * them from the caches if we abort the transaction. Similarly, we'd better
27 * be able to flush "negative" cache entries that may have been loaded in
28 * place of deleted tuples, so we still need the deleted ones too.
30 * If we successfully complete the transaction, we have to broadcast all
31 * these invalidation events to other backends (via the SI message queue)
32 * so that they can flush obsolete entries from their caches. Note we have
33 * to record the transaction commit before sending SI messages, otherwise
34 * the other backends won't see our updated tuples as good.
36 * When a subtransaction aborts, we can process and discard any events
37 * it has queued. When a subtransaction commits, we just add its events
38 * to the pending lists of the parent transaction.
40 * In short, we need to remember until xact end every insert or delete
41 * of a tuple that might be in the system caches. Updates are treated as
42 * two events, delete + insert, for simplicity. (If the update doesn't
43 * change the tuple hash value, catcache.c optimizes this into one event.)
45 * We do not need to register EVERY tuple operation in this way, just those
46 * on tuples in relations that have associated catcaches. We do, however,
47 * have to register every operation on every tuple that *could* be in a
48 * catcache, whether or not it currently is in our cache. Also, if the
49 * tuple is in a relation that has multiple catcaches, we need to register
50 * an invalidation message for each such catcache. catcache.c's
51 * PrepareToInvalidateCacheTuple() routine provides the knowledge of which
52 * catcaches may need invalidation for a given tuple.
54 * Also, whenever we see an operation on a pg_class, pg_attribute, or
55 * pg_index tuple, we register a relcache flush operation for the relation
56 * described by that tuple (as specified in CacheInvalidateHeapTuple()).
57 * Likewise for pg_constraint tuples for foreign keys on relations.
59 * We keep the relcache flush requests in lists separate from the catcache
60 * tuple flush requests. This allows us to issue all the pending catcache
61 * flushes before we issue relcache flushes, which saves us from loading
62 * a catcache tuple during relcache load only to flush it again right away.
63 * Also, we avoid queuing multiple relcache flush requests for the same
64 * relation, since a relcache flush is relatively expensive to do.
65 * (XXX is it worth testing likewise for duplicate catcache flush entries?
68 * Many subsystems own higher-level caches that depend on relcache and/or
69 * catcache, and they register callbacks here to invalidate their caches.
70 * While building a higher-level cache entry, a backend may receive a
71 * callback for the being-built entry or one of its dependencies. This
72 * implies the new higher-level entry would be born stale, and it might
73 * remain stale for the life of the backend. Many caches do not prevent
74 * that. They rely on DDL for can't-miss catalog changes taking
75 * AccessExclusiveLock on suitable objects. (For a change made with less
76 * locking, backends might never read the change.) The relation cache,
77 * however, needs to reflect changes from CREATE INDEX CONCURRENTLY no later
78 * than the beginning of the next transaction. Hence, when a relevant
79 * invalidation callback arrives during a build, relcache.c reattempts that
80 * build. Caches with similar needs could do likewise.
82 * If a relcache flush is issued for a system relation that we preload
83 * from the relcache init file, we must also delete the init file so that
84 * it will be rebuilt during the next backend restart. The actual work of
85 * manipulating the init file is in relcache.c, but we keep track of the
88 * Currently, inval messages are sent without regard for the possibility
89 * that the object described by the catalog tuple might be a session-local
90 * object such as a temporary table. This is because (1) this code has
91 * no practical way to tell the difference, and (2) it is not certain that
92 * other backends don't have catalog cache or even relcache entries for
93 * such tables, anyway; there is nothing that prevents that. It might be
94 * worth trying to avoid sending such inval traffic in the future, if those
95 * problems can be overcome cheaply.
97 * When making a nontransactional change to a cacheable object, we must
98 * likewise send the invalidation immediately, before ending the change's
99 * critical section. This includes inplace heap updates, relmap, and smgr.
101 * When wal_level=logical, write invalidations into WAL at each command end to
102 * support the decoding of the in-progress transactions. See
103 * CommandEndInvalidationMessages.
105 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
106 * Portions Copyright (c) 1994, Regents of the University of California
109 * src/backend/utils/cache/inval.c
111 *-------------------------------------------------------------------------
138 * Pending requests are stored as ready-to-send SharedInvalidationMessages.
139 * We keep the messages themselves in arrays in TopTransactionContext (there
140 * are separate arrays for catcache and relcache messages). For transactional
141 * messages, control information is kept in a chain of TransInvalidationInfo
142 * structs, also allocated in TopTransactionContext. (We could keep a
143 * subtransaction's TransInvalidationInfo in its CurTransactionContext; but
144 * that's more wasteful not less so, since in very many scenarios it'd be the
145 * only allocation in the subtransaction's CurTransactionContext.) For
146 * inplace update messages, control information appears in an
147 * InvalidationInfo, allocated in CurrentMemoryContext.
149 * We can store the message arrays densely, and yet avoid moving data around
150 * within an array, because within any one subtransaction we need only
151 * distinguish between messages emitted by prior commands and those emitted
152 * by the current command. Once a command completes and we've done local
153 * processing on its messages, we can fold those into the prior-commands
154 * messages just by changing array indexes in the TransInvalidationInfo
155 * struct. Similarly, we need distinguish messages of prior subtransactions
156 * from those of the current subtransaction only until the subtransaction
157 * completes, after which we adjust the array indexes in the parent's
158 * TransInvalidationInfo to include the subtransaction's messages. Inplace
159 * invalidations don't need a concept of command or subtransaction boundaries,
160 * since we send them during the WAL insertion critical section.
162 * The ordering of the individual messages within a command's or
163 * subtransaction's output is not considered significant, although this
164 * implementation happens to preserve the order in which they were queued.
165 * (Previous versions of this code did not preserve it.)
167 * For notational convenience, control information is kept in two-element
168 * arrays, the first for catcache messages and the second for relcache
171 #define CatCacheMsgs 0
172 #define RelCacheMsgs 1
174/* Pointers to main arrays in TopTransactionContext */
178 int maxmsgs;
/* current allocated size of array */
183/* Control information for one logical group of messages */
186 int firstmsg[2];
/* first index in relevant array */
190/* Macros to help preserve InvalidationMsgsGroup abstraction */
191 #define SetSubGroupToFollow(targetgroup, priorgroup, subgroup) \
193 (targetgroup)->firstmsg[subgroup] = \
194 (targetgroup)->nextmsg[subgroup] = \
195 (priorgroup)->nextmsg[subgroup]; \
198 #define SetGroupToFollow(targetgroup, priorgroup) \
200 SetSubGroupToFollow(targetgroup, priorgroup, CatCacheMsgs); \
201 SetSubGroupToFollow(targetgroup, priorgroup, RelCacheMsgs); \
204 #define NumMessagesInSubGroup(group, subgroup) \
205 ((group)->nextmsg[subgroup] - (group)->firstmsg[subgroup])
207 #define NumMessagesInGroup(group) \
208 (NumMessagesInSubGroup(group, CatCacheMsgs) + \
209 NumMessagesInSubGroup(group, RelCacheMsgs))
213 * Transactional invalidation messages are divided into two groups:
214 * 1) events so far in current command, not yet reflected to caches.
215 * 2) events in previous commands of current transaction; these have
216 * been reflected to local caches, and must be either broadcast to
217 * other backends or rolled back from local cache when we commit
218 * or abort the transaction.
219 * Actually, we need such groups for each level of nested transaction,
220 * so that we can discard events from an aborted subtransaction. When
221 * a subtransaction commits, we append its events to the parent's groups.
223 * The relcache-file-invalidated flag can just be a simple boolean,
224 * since we only act on it at transaction commit; we don't care which
225 * command of the transaction set it.
229/* fields common to both transactional and inplace invalidation */
232 /* Events emitted by current command */
235 /* init file must be invalidated? */
239/* subclass adding fields specific to transactional invalidation */
245 /* Events emitted by previous commands of this (sub)transaction */
248 /* Back link to parent transaction's info */
251 /* Subtransaction nesting depth */
263 * Dynamically-registered callback functions. Current implementation
264 * assumes there won't be enough of these to justify a dynamically resizable
265 * array; it'd be easy to improve that if needed.
267 * To avoid searching in CallSyscacheCallbacks, all callbacks for a given
268 * syscache are linked into a list pointed to by syscache_callback_links[id].
269 * The link values are syscache_callback_list[] index plus 1, or 0 for none.
272 #define MAX_SYSCACHE_CALLBACKS 64
273 #define MAX_RELCACHE_CALLBACKS 10
274 #define MAX_RELSYNC_CALLBACKS 10
305/* ----------------------------------------------------------------
306 * Invalidation subgroup support functions
307 * ----------------------------------------------------------------
311 * AddInvalidationMessage
312 * Add an invalidation message to a (sub)group.
314 * The group must be the last active one, since we assume we can add to the
315 * end of the relevant InvalMessageArray.
317 * subgroup must be CatCacheMsgs or RelCacheMsgs.
324 int nextindex = group->
nextmsg[subgroup];
328 if (ima->
msgs == NULL)
330 /* Create new storage array in TopTransactionContext */
331 int reqsize = 32;
/* arbitrary */
341 /* Enlarge storage array */
342 int reqsize = 2 * ima->
maxmsgs;
350 /* Okay, add message to current group */
351 ima->
msgs[nextindex] = *msg;
356 * Append one subgroup of invalidation messages to another, resetting
357 * the source subgroup to empty.
364 /* Messages must be adjacent in main array */
367 /* ... which makes this easy: */
371 * This is handy for some callers and irrelevant for others. But we do it
372 * always, reasoning that it's bad to leave different groups pointing at
373 * the same fragment of the message array.
379 * Process a subgroup of invalidation messages.
381 * This is a macro that executes the given code fragment for each message in
382 * a message subgroup. The fragment should refer to the message as *msg.
384 #define ProcessMessageSubGroup(group, subgroup, codeFragment) \
386 int _msgindex = (group)->firstmsg[subgroup]; \
387 int _endmsg = (group)->nextmsg[subgroup]; \
388 for (; _msgindex < _endmsg; _msgindex++) \
390 SharedInvalidationMessage *msg = \
391 &InvalMessageArrays[subgroup].msgs[_msgindex]; \
397 * Process a subgroup of invalidation messages as an array.
399 * As above, but the code fragment can handle an array of messages.
400 * The fragment should refer to the messages as msgs[], with n entries.
402 #define ProcessMessageSubGroupMulti(group, subgroup, codeFragment) \
404 int n = NumMessagesInSubGroup(group, subgroup); \
406 SharedInvalidationMessage *msgs = \
407 &InvalMessageArrays[subgroup].msgs[(group)->firstmsg[subgroup]]; \
413/* ----------------------------------------------------------------
414 * Invalidation group support functions
416 * These routines understand about the division of a logical invalidation
417 * group into separate physical arrays for catcache and relcache entries.
418 * ----------------------------------------------------------------
422 * Add a catcache inval entry
436 * Define padding bytes in SharedInvalidationMessage structs to be
437 * defined. Otherwise the sinvaladt.c ringbuffer, which is accessed by
438 * multiple processes, will cause spurious valgrind warnings about
439 * undefined memory being used. That's because valgrind remembers the
440 * undefined bytes from the last local process's store, not realizing that
441 * another process has written since, filling the previously uninitialized
450 * Add a whole-catalog inval entry
461 /* check AddCatcacheInvalidationMessage() for an explanation */
468 * Add a relcache inval entry
477 * Don't add a duplicate item. We assume dbId need not be checked because
478 * it will never change. InvalidOid for relId means all relations so we
479 * don't need to add individual ones when it is present.
487 /* OK, add the item */
491 /* check AddCatcacheInvalidationMessage() for an explanation */
498 * Add a relsync inval entry
500 * We put these into the relcache subgroup for simplicity. This message is the
501 * same as AddRelcacheInvalidationMessage() except that it is for
502 * RelationSyncCache maintained by decoding plugin pgoutput.
510 /* Don't add a duplicate item. */
517 /* OK, add the item */
521 /* check AddCatcacheInvalidationMessage() for an explanation */
528 * Add a snapshot inval entry
530 * We put these into the relcache subgroup for simplicity.
538 /* Don't add a duplicate item */
539 /* We assume dbId need not be checked because it will never change */
545 /* OK, add the item */
549 /* check AddCatcacheInvalidationMessage() for an explanation */
556 * Append one group of invalidation messages to another, resetting
557 * the source group to empty.
568 * Execute the given function for all the messages in an invalidation group.
569 * The group is not altered.
571 * catcache entries are processed first, for reasons mentioned above.
582 * As above, but the function is able to process an array of messages
583 * rather than just one at a time.
593/* ----------------------------------------------------------------
594 * private support functions
595 * ----------------------------------------------------------------
599 * RegisterCatcacheInvalidation
601 * Register an invalidation event for a catcache tuple entry.
612 cacheId, hashValue, dbId);
616 * RegisterCatalogInvalidation
618 * Register an invalidation event for all catcache entries from a catalog.
627 * RegisterRelcacheInvalidation
629 * As above, but register a relcache invalidation event.
637 * Most of the time, relcache invalidation is associated with system
638 * catalog updates, but there are a few cases where it isn't. Quick hack
639 * to ensure that the next CommandCounterIncrement() will think that we
640 * need to do CommandEndInvalidationMessages().
645 * If the relation being invalidated is one of those cached in a relcache
646 * init file, mark that we need to zap that file at commit. For simplicity
647 * invalidations for a specific database always invalidate the shared file
648 * as well. Also zap when we are invalidating whole relcache.
655 * RegisterRelsyncInvalidation
657 * As above, but register a relsynccache invalidation event.
666 * RegisterSnapshotInvalidation
668 * Register an invalidation event for MVCC scans against a given catalog.
669 * Only needed for catalogs that don't have catcaches.
678 * PrepareInvalidationState
679 * Initialize inval data for the current (sub)transaction.
686 /* PrepareToInvalidateCacheTuple() needs relcache */
688 /* Can't queue transactional message while collecting inplace messages. */
701 /* Now, do we have a previous stack entry? */
704 /* Yes; this one should be for a deeper nesting level. */
708 * The parent (sub)transaction must not have any current (i.e.,
709 * not-yet-locally-processed) messages. If it did, we'd have a
710 * semantic problem: the new subtransaction presumably ought not be
711 * able to see those events yet, but since the CommandCounter is
712 * linear, that can't work once the subtransaction advances the
713 * counter. This is a convenient place to check for that, as well as
714 * being important to keep management of the message arrays simple.
717 elog(
ERROR,
"cannot start a subtransaction when there are unprocessed inval messages");
720 * MemoryContextAllocZero set firstmsg = nextmsg = 0 in each group,
721 * which is fine for the first (sub)transaction, but otherwise we need
722 * to update them to follow whatever is already in the arrays.
732 * Here, we need only clear any array pointers left over from a prior
746 * PrepareInplaceInvalidationState
747 * Initialize inval data for an inplace update.
749 * See previous function for more background.
757 /* limit of one inplace update under assembly */
760 /* gone after WAL insertion CritSection ends, so use current context */
763 /* Stash our messages past end of the transactional messages, if any. */
779/* ----------------------------------------------------------------
781 * ----------------------------------------------------------------
816 * LocalExecuteInvalidationMessage
818 * Process a single invalidation message (which could be of any type).
819 * Only the local caches are flushed; this does not transmit the message
844 /* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
869 * We could have smgr entries for relations of other databases, so no
870 * short-circuit test is possible here.
880 /* We only care about our own database and shared catalogs */
888 /* We only care about our own database and shared catalogs */
896 /* We only care about our own database */
901 elog(
FATAL,
"unrecognized SI message ID: %d", msg->
id);
905 * InvalidateSystemCaches
907 * This blows away all tuples in the system catalog caches and
908 * all the cached relation descriptors and smgr cache entries.
909 * Relation descriptors that have positive refcounts are then rebuilt.
911 * We call this when we see a shared-inval-queue overflow signal,
912 * since that tells us we've lost some shared-inval messages and hence
913 * don't know what needs to be invalidated.
922 * AcceptInvalidationMessages
923 * Read and process invalidation messages from the shared invalidation
927 * This should be called as the first step in processing a transaction.
932#ifdef USE_ASSERT_CHECKING
933 /* message handlers shall access catalogs only during transactions */
942 * Test code to force cache flushes anytime a flush could happen.
944 * This helps detect intermittent faults caused by code that reads a cache
945 * entry and then performs an action that could invalidate the entry, but
946 * rarely actually does so. This can spot issues that would otherwise
947 * only arise with badly timed concurrent DDL, for example.
949 * The default debug_discard_caches = 0 does no forced cache flushes.
951 * If used with CLOBBER_FREED_MEMORY,
952 * debug_discard_caches = 1 (formerly known as CLOBBER_CACHE_ALWAYS)
953 * provides a fairly thorough test that the system contains no cache-flush
954 * hazards. However, it also makes the system unbelievably slow --- the
955 * regression tests take about 100 times longer than normal.
957 * If you're a glutton for punishment, try
958 * debug_discard_caches = 3 (formerly known as CLOBBER_CACHE_RECURSIVELY).
959 * This slows things by at least a factor of 10000, so I wouldn't suggest
960 * trying to run the entire regression tests that way. It's useful to try
961 * a few simple tests, to make sure that cache reload isn't subject to
962 * internal cache-flush hazards, but after you've done a few thousand
963 * recursive reloads it's unlikely you'll learn more.
966#ifdef DISCARD_CACHES_ENABLED
982 * Clean up after successful PREPARE.
984 * Here, we want to act as though the transaction aborted, so that we will
985 * undo any syscache changes it made, thereby bringing us into sync with the
986 * outside world, which doesn't believe the transaction committed yet.
988 * If the prepared transaction is later aborted, there is nothing more to
989 * do; if it commits, we will receive the consequent inval messages just
990 * like everyone else.
999 * xactGetCommittedInvalidationMessages() is called by
1000 * RecordTransactionCommit() to collect invalidation messages to add to the
1001 * commit record. This applies only to commit message types, never to
1002 * abort records. Must always run before AtEOXact_Inval(), since that
1003 * removes the data we need to see.
1005 * Remember that this runs before we have officially committed, so we
1006 * must not do anything here to change what might occur *if* we should
1007 * fail between here and the actual commit.
1009 * see also xact_redo_commit() and xact_desc_commit()
1013 bool *RelcacheInitFileInval)
1019 /* Quick exit if we haven't done anything with invalidation messages. */
1022 *RelcacheInitFileInval =
false;
1027 /* Must be at top of stack */
1031 * Relcache init file invalidation requires processing both before and
1032 * after we send the SI messages. However, we need not do anything unless
1038 * Collect all the pending messages into a single contiguous array of
1039 * invalidation messages, to simplify what needs to happen while building
1040 * the commit WAL message. Maintain the order that they would be
1041 * processed in by AtEOXact_Inval(), to ensure emulated behaviour in redo
1042 * is as similar as possible to original. We want the same bugs, if any,
1055 (memcpy(msgarray + nmsgs,
1061 (memcpy(msgarray + nmsgs,
1067 (memcpy(msgarray + nmsgs,
1073 (memcpy(msgarray + nmsgs,
1077 Assert(nmsgs == nummsgs);
1083 * inplaceGetInvalidationMessages() is called by the inplace update to collect
1084 * invalidation messages to add to its WAL record. Like the previous
1085 * function, we might still fail.
1089 bool *RelcacheInitFileInval)
1095 /* Quick exit if we haven't done anything with invalidation messages. */
1098 *RelcacheInitFileInval =
false;
1111 (memcpy(msgarray + nmsgs,
1117 (memcpy(msgarray + nmsgs,
1121 Assert(nmsgs == nummsgs);
1127 * ProcessCommittedInvalidationMessages is executed by xact_redo_commit() or
1128 * standby_redo() to process invalidation messages. Currently that happens
1129 * only at end-of-xact.
1131 * Relcache init file invalidation requires processing both
1132 * before and after we send the SI messages. See AtEOXact_Inval()
1136 int nmsgs,
bool RelcacheInitFileInval,
1142 elog(
DEBUG4,
"replaying commit with %d messages%s", nmsgs,
1143 (RelcacheInitFileInval ?
" and relcache file invalidation" :
""));
1145 if (RelcacheInitFileInval)
1147 elog(
DEBUG4,
"removing relcache init files for database %u", dbid);
1150 * RelationCacheInitFilePreInvalidate, when the invalidation message
1151 * is for a specific database, requires DatabasePath to be set, but we
1152 * should not use SetDatabasePath during recovery, since it is
1153 * intended to be used only once by normal backends. Hence, a quick
1154 * hack: set DatabasePath directly then unset after use.
1170 if (RelcacheInitFileInval)
1176 * Process queued-up invalidation messages at end of main transaction.
1178 * If isCommit, we must send out the messages in our PriorCmdInvalidMsgs list
1179 * to the shared invalidation message queue. Note that these will be read
1180 * not only by other backends, but also by our own backend at the next
1181 * transaction start (via AcceptInvalidationMessages). This means that
1182 * we can skip immediate local processing of anything that's still in
1183 * CurrentCmdInvalidMsgs, and just send that list out too.
1185 * If not isCommit, we are aborting, and must locally process the messages
1186 * in PriorCmdInvalidMsgs. No messages need be sent to other backends,
1187 * since they'll not have seen our changed tuples anyway. We can forget
1188 * about CurrentCmdInvalidMsgs too, since those changes haven't touched
1191 * In any case, reset our state to empty. We need not physically
1192 * free memory here, since TopTransactionContext is about to be emptied
1196 * This should be called as the last step in processing a transaction.
1203 /* Quick exit if no transactional messages */
1207 /* Must be at top of stack */
1215 * Relcache init file invalidation requires processing both before and
1216 * after we send the SI messages. However, we need not do anything
1217 * unless we committed.
1237 /* Need not free anything explicitly */
1243 * Process queued-up invalidation before inplace update critical section.
1245 * Tasks belong here if they are safe even if the inplace update does not
1246 * complete. Currently, this just unlinks a cache file, which can fail. The
1247 * sum of this and AtInplace_Inval() mirrors AtEOXact_Inval(isCommit=true).
1260 * Process queued-up invalidations after inplace update buffer mutation.
1280 * ForgetInplace_Inval
1281 * Alternative to PreInplace_Inval()+AtInplace_Inval(): discard queued-up
1282 * invalidations. This lets inplace update enumerate invalidations
1283 * optimistically, before locking the buffer.
1293 * Process queued-up invalidation messages at end of subtransaction.
1295 * If isCommit, process CurrentCmdInvalidMsgs if any (there probably aren't),
1296 * and then attach both CurrentCmdInvalidMsgs and PriorCmdInvalidMsgs to the
1297 * parent's PriorCmdInvalidMsgs list.
1299 * If not isCommit, we are aborting, and must locally process the messages
1300 * in PriorCmdInvalidMsgs. No messages need be sent to other backends.
1301 * We can forget about CurrentCmdInvalidMsgs too, since those changes haven't
1302 * touched the caches yet.
1304 * In any case, pop the transaction stack. We need not physically free memory
1305 * here, since CurTransactionContext is about to be emptied anyway
1306 * (if aborting). Beware of the possibility of aborting the same nesting
1307 * level twice, though.
1316 * Successful inplace update must clear this, but we clear it on abort.
1317 * Inplace updates allocate this in CurrentMemoryContext, which has
1318 * lifespan <= subtransaction lifespan. Hence, don't free it explicitly.
1325 /* Quick exit if no transactional messages. */
1330 /* Also bail out quickly if messages are not for this level. */
1340 /* If CurrentCmdInvalidMsgs still has anything, fix it */
1344 * We create invalidation stack entries lazily, so the parent might
1345 * not have one. Instead of creating one, moving all the data over,
1346 * and then freeing our own, we can just adjust the level of our own
1356 * Pass up my inval messages to parent. Notice that we stick them in
1357 * PriorCmdInvalidMsgs, not CurrentCmdInvalidMsgs, since they've
1358 * already been locally processed. (This would trigger the Assert in
1359 * AppendInvalidationMessageSubGroup if the parent's
1360 * CurrentCmdInvalidMsgs isn't empty; but we already checked that in
1361 * PrepareInvalidationState.)
1366 /* Must readjust parent's CurrentCmdInvalidMsgs indexes now */
1370 /* Pending relcache inval becomes parent's problem too */
1374 /* Pop the transaction state stack */
1377 /* Need not free anything else explicitly */
1385 /* Pop the transaction state stack */
1388 /* Need not free anything else explicitly */
1394 * CommandEndInvalidationMessages
1395 * Process queued-up invalidation messages at end of one command
1398 * Here, we send no messages to the shared queue, since we don't know yet if
1399 * we will commit. We do need to locally process the CurrentCmdInvalidMsgs
1400 * list, so as to flush our caches of any entries we have outdated in the
1401 * current command. We then move the current-cmd list over to become part
1402 * of the prior-cmds list.
1405 * This should be called during CommandCounterIncrement(),
1406 * after we have advanced the command ID.
1412 * You might think this shouldn't be called outside any transaction, but
1413 * bootstrap does it, and also ABORT issued when not in a transaction. So
1414 * just quietly return if no state to work on.
1422 /* WAL Log per-command invalidation messages for wal_level=logical */
1432 * CacheInvalidateHeapTupleCommon
1433 * Common logic for end-of-command and inplace variants.
1446 /* PrepareToInvalidateCacheTuple() needs relcache */
1449 /* Do nothing during bootstrap */
1454 * We only need to worry about invalidation for tuples that are in system
1455 * catalogs; user-relation tuples are never in catcaches and can't affect
1456 * the relcache either.
1462 * IsCatalogRelation() will return true for TOAST tables of system
1463 * catalogs, but we don't care about those, either.
1468 /* Allocate any required resources. */
1469 info = prepare_callback();
1472 * First let the catcache do its thing
1486 * Now, is this tuple one of the primary definers of a relcache entry? See
1487 * comments in file header for deeper explanation.
1489 * Note we ignore newtuple here; we assume an update cannot move a tuple
1490 * from being part of one relcache entry to being part of another.
1492 if (tupleRelId == RelationRelationId)
1496 relationId = classtup->oid;
1497 if (classtup->relisshared)
1502 else if (tupleRelId == AttributeRelationId)
1506 relationId = atttup->attrelid;
1509 * KLUGE ALERT: we always send the relcache event with MyDatabaseId,
1510 * even if the rel in question is shared (which we can't easily tell).
1511 * This essentially means that only backends in this same database
1512 * will react to the relcache flush request. This is in fact
1513 * appropriate, since only those backends could see our pg_attribute
1514 * change anyway. It looks a bit ugly though. (In practice, shared
1515 * relations can't have schema changes after bootstrap, so we should
1516 * never come here for a shared rel anyway.)
1520 else if (tupleRelId == IndexRelationId)
1525 * When a pg_index row is updated, we should send out a relcache inval
1526 * for the index relation. As above, we don't know the shared status
1527 * of the index, but in practice it doesn't matter since indexes of
1528 * shared catalogs can't have such updates.
1530 relationId = indextup->indexrelid;
1533 else if (tupleRelId == ConstraintRelationId)
1538 * Foreign keys are part of relcache entries, too, so send out an
1539 * inval for the table that the FK applies to.
1541 if (constrtup->contype == CONSTRAINT_FOREIGN &&
1544 relationId = constrtup->conrelid;
1554 * Yes. We need to register a relcache invalidation event.
1560 * CacheInvalidateHeapTuple
1561 * Register the given tuple for invalidation at end of command
1562 * (ie, current command is creating or outdating this tuple) and end of
1563 * transaction. Also, detect whether a relcache invalidation is implied.
1565 * For an insert or delete, tuple is the target tuple and newtuple is NULL.
1566 * For an update, we are called just once, with tuple being the old tuple
1567 * version and newtuple the new version. This allows avoidance of duplicate
1568 * effort during an update.
1580 * CacheInvalidateHeapTupleInplace
1581 * Register the given tuple for nontransactional invalidation pertaining
1582 * to an inplace update. Also, detect whether a relcache invalidation is
1585 * Like CacheInvalidateHeapTuple(), but for inplace updates.
1597 * CacheInvalidateCatalog
1598 * Register invalidation of the whole content of a system catalog.
1600 * This is normally used in VACUUM FULL/CLUSTER, where we haven't so much
1601 * changed any tuples as moved them around. Some uses of catcache entries
1602 * expect their TIDs to be correct, so we have to blow away the entries.
1604 * Note: we expect caller to verify that the rel actually is a system
1605 * catalog. If it isn't, no great harm is done, just a wasted sinval message.
1618 databaseId, catalogId);
1622 * CacheInvalidateRelcache
1623 * Register invalidation of the specified relation's relcache entry
1624 * at end of command.
1626 * This is used in places that need to force relcache rebuild but aren't
1627 * changing any of the tuples recognized as contributors to the relcache
1628 * entry by CacheInvalidateHeapTuple. (An example is dropping an index.)
1637 if (relation->
rd_rel->relisshared)
1643 databaseId, relationId);
1647 * CacheInvalidateRelcacheAll
1648 * Register invalidation of the whole relcache at the end of command.
1650 * This is used by alter publication as changes in publications may affect
1651 * large number of tables.
1661 * CacheInvalidateRelcacheByTuple
1662 * As above, but relation is identified by passing its pg_class tuple.
1671 relationId = classtup->oid;
1672 if (classtup->relisshared)
1677 databaseId, relationId);
1681 * CacheInvalidateRelcacheByRelid
1682 * As above, but relation is identified by passing its OID.
1683 * This is the least efficient of the three options; use one of
1684 * the above routines if you have a Relation or pg_class tuple.
1693 elog(
ERROR,
"cache lookup failed for relation %u", relid);
1699 * CacheInvalidateRelSync
1700 * Register invalidation of the cache in logical decoding output plugin
1703 * This type of invalidation message is used for the specific purpose of output
1704 * plugins. Processes which do not decode WALs would do nothing even when it
1705 * receives the message.
1715 * CacheInvalidateRelSyncAll
1716 * Register invalidation of the whole cache in logical decoding output
1726 * CacheInvalidateSmgr
1727 * Register invalidation of smgr references to a physical relation.
1729 * Sending this type of invalidation msg forces other backends to close open
1730 * smgr entries for the rel. This should be done to flush dangling open-file
1731 * references when the physical rel is being dropped or truncated. Because
1732 * these are nontransactional (i.e., not-rollback-able) operations, we just
1733 * send the inval message immediately without any queuing.
1735 * Note: in most cases there will have been a relcache flush issued against
1736 * the rel at the logical level. We need a separate smgr-level flush because
1737 * it is possible for backends to have open smgr entries for rels they don't
1738 * have a relcache entry for, e.g. because the only thing they ever did with
1739 * the rel is write out dirty shared buffers.
1741 * Note: because these messages are nontransactional, they won't be captured
1742 * in commit/abort WAL entries. Instead, calls to CacheInvalidateSmgr()
1743 * should happen in low-level smgr.c routines, which are executed while
1744 * replaying WAL as well as when creating it.
1746 * Note: In order to avoid bloating SharedInvalidationMessage, we store only
1747 * three bytes of the ProcNumber using what would otherwise be padding space.
1748 * Thus, the maximum possible ProcNumber is 2^23-1.
1755 /* verify optimization stated above stays valid */
1757 "MAX_BACKENDS_BITS is too big for inval.c");
1763 /* check AddCatcacheInvalidationMessage() for an explanation */
1770 * CacheInvalidateRelmap
1771 * Register invalidation of the relation mapping for a database,
1772 * or for the shared catalogs if databaseId is zero.
1774 * Sending this type of invalidation msg forces other backends to re-read
1775 * the indicated relation mapping file. It is also necessary to send a
1776 * relcache inval for the specific relations whose mapping has been altered,
1777 * else the relcache won't get updated with the new filenode data.
1779 * Note: because these messages are nontransactional, they won't be captured
1780 * in commit/abort WAL entries. Instead, calls to CacheInvalidateRelmap()
1781 * should happen in low-level relmapper.c routines, which are executed while
1782 * replaying WAL as well as when creating it.
1790 msg.
rm.
dbId = databaseId;
1791 /* check AddCatcacheInvalidationMessage() for an explanation */
1799 * CacheRegisterSyscacheCallback
1800 * Register the specified function to be called for all future
1801 * invalidation events in the specified cache. The cache ID and the
1802 * hash value of the tuple being invalidated will be passed to the
1805 * NOTE: Hash value zero will be passed if a cache reset request is received.
1806 * In this case the called routines should flush all cached state.
1807 * Yes, there's a possibility of a false match to zero, but it doesn't seem
1808 * worth troubling over, especially since most of the current callees just
1809 * flush all cached state anyway.
1816 if (cacheid < 0 || cacheid >= SysCacheSize)
1817 elog(
FATAL,
"invalid cache ID: %d", cacheid);
1819 elog(
FATAL,
"out of syscache_callback_list slots");
1823 /* first callback for this cache */
1828 /* add to end of chain, so that older callbacks are called first */
1845 * CacheRegisterRelcacheCallback
1846 * Register the specified function to be called for all future
1847 * relcache invalidation events. The OID of the relation being
1848 * invalidated will be passed to the function.
1850 * NOTE: InvalidOid will be passed if a cache reset request is received.
1851 * In this case the called routines should flush all cached state.
1858 elog(
FATAL,
"out of relcache_callback_list slots");
1867 * CacheRegisterRelSyncCallback
1868 * Register the specified function to be called for all future
1869 * relsynccache invalidation events.
1871 * This function is intended to be call from the logical decoding output
1879 elog(
FATAL,
"out of relsync_callback_list slots");
1888 * CallSyscacheCallbacks
1890 * This is exported so that CatalogCacheFlushCatalog can call it, saving
1891 * this module from knowing which catcache IDs correspond to which catalogs.
1898 if (cacheid < 0 || cacheid >= SysCacheSize)
1899 elog(
ERROR,
"invalid cache ID: %d", cacheid);
1907 ccitem->
function(ccitem->
arg, cacheid, hashvalue);
1908 i = ccitem->
link - 1;
1913 * CallSyscacheCallbacks
1927 * LogLogicalInvalidations
1929 * Emit WAL for invalidations caused by the current command.
1931 * This is currently only used for logging invalidations at the command end
1932 * or at commit time if any invalidations are pending.
1941 /* Quick exit if we haven't done anything with invalidation messages. */
1950 /* prepare record */
1952 xlrec.
nmsgs = nmsgs;
1954 /* perform insertion */
#define StaticAssertStmt(condition, errmessage)
#define OidIsValid(objectId)
bool IsToastRelation(Relation relation)
bool IsCatalogRelation(Relation relation)
bool IsSharedRelation(Oid relationId)
void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid, void *), void *context)
void CatalogCacheFlushCatalog(Oid catId)
void ResetCatalogCachesExt(bool debug_discard)
static int recursion_depth
volatile uint32 CritSectionCount
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
#define INJECTION_POINT(name, arg)
void PostPrepare_Inval(void)
void InvalidateSystemCachesExtended(bool debug_discard)
void CallRelSyncCallbacks(Oid relid)
static void AddCatcacheInvalidationMessage(InvalidationMsgsGroup *group, int id, uint32 hashValue, Oid dbId)
void CacheInvalidateRelSyncAll(void)
static void AddCatalogInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid catId)
static void RegisterRelcacheInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
static int relcache_callback_count
#define NumMessagesInGroup(group)
static void AddRelcacheInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
static int relsync_callback_count
static void AddRelsyncInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
void LogLogicalInvalidations(void)
void CacheInvalidateHeapTupleInplace(Relation relation, HeapTuple tuple, HeapTuple newtuple)
void AcceptInvalidationMessages(void)
static void ProcessInvalidationMessages(InvalidationMsgsGroup *group, void(*func)(SharedInvalidationMessage *msg))
void CacheInvalidateRelmap(Oid databaseId)
void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
struct TransInvalidationInfo TransInvalidationInfo
static void RegisterCatcacheInvalidation(int cacheId, uint32 hashValue, Oid dbId, void *context)
void CacheInvalidateCatalog(Oid catalogId)
#define ProcessMessageSubGroupMulti(group, subgroup, codeFragment)
static struct RELSYNCCALLBACK relsync_callback_list[MAX_RELSYNC_CALLBACKS]
static InvalidationInfo * inplaceInvalInfo
static void AppendInvalidationMessageSubGroup(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src, int subgroup)
static void RegisterSnapshotInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
struct InvalidationInfo InvalidationInfo
static struct SYSCACHECALLBACK syscache_callback_list[MAX_SYSCACHE_CALLBACKS]
static struct RELCACHECALLBACK relcache_callback_list[MAX_RELCACHE_CALLBACKS]
static TransInvalidationInfo * transInvalInfo
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
#define ProcessMessageSubGroup(group, subgroup, codeFragment)
void CacheInvalidateRelcache(Relation relation)
static InvalidationInfo * PrepareInvalidationState(void)
static void AppendInvalidationMessages(InvalidationMsgsGroup *dest, InvalidationMsgsGroup *src)
#define MAX_RELSYNC_CALLBACKS
static void ProcessInvalidationMessagesMulti(InvalidationMsgsGroup *group, void(*func)(const SharedInvalidationMessage *msgs, int n))
int inplaceGetInvalidationMessages(SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval)
void CacheInvalidateRelcacheByRelid(Oid relid)
void InvalidateSystemCaches(void)
void AtEOXact_Inval(bool isCommit)
#define MAX_SYSCACHE_CALLBACKS
void CacheInvalidateSmgr(RelFileLocatorBackend rlocator)
#define SetGroupToFollow(targetgroup, priorgroup)
void AtEOSubXact_Inval(bool isCommit)
static void AddSnapshotInvalidationMessage(InvalidationMsgsGroup *group, Oid dbId, Oid relId)
static int16 syscache_callback_links[SysCacheSize]
static void AddInvalidationMessage(InvalidationMsgsGroup *group, int subgroup, const SharedInvalidationMessage *msg)
void PreInplace_Inval(void)
struct InvalMessageArray InvalMessageArray
void CommandEndInvalidationMessages(void)
void AtInplace_Inval(void)
static void RegisterCatalogInvalidation(InvalidationInfo *info, Oid dbId, Oid catId)
#define MAX_RELCACHE_CALLBACKS
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
void CacheRegisterRelSyncCallback(RelSyncCallbackFunction func, Datum arg)
void ForgetInplace_Inval(void)
#define SetSubGroupToFollow(targetgroup, priorgroup, subgroup)
struct InvalidationMsgsGroup InvalidationMsgsGroup
void CacheInvalidateRelSync(Oid relid)
static InvalidationInfo * PrepareInplaceInvalidationState(void)
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
static void CacheInvalidateHeapTupleCommon(Relation relation, HeapTuple tuple, HeapTuple newtuple, InvalidationInfo *(*prepare_callback)(void))
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
static InvalMessageArray InvalMessageArrays[2]
static int syscache_callback_count
static void RegisterRelsyncInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
void CacheInvalidateRelcacheAll(void)
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
void(* SyscacheCallbackFunction)(Datum arg, int cacheid, uint32 hashvalue)
void(* RelcacheCallbackFunction)(Datum arg, Oid relid)
void(* RelSyncCallbackFunction)(Datum arg, Oid relid)
void * MemoryContextAlloc(MemoryContext context, Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
MemoryContext TopTransactionContext
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurTransactionContext
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
#define IsBootstrapProcessingMode()
FormData_pg_attribute * Form_pg_attribute
FormData_pg_class * Form_pg_class
FormData_pg_constraint * Form_pg_constraint
FormData_pg_index * Form_pg_index
static Datum ObjectIdGetDatum(Oid X)
#define MAX_BACKENDS_BITS
#define RelationGetRelid(relation)
void RelationCacheInvalidate(bool debug_discard)
void RelationCacheInitFilePostInvalidate(void)
void RelationCacheInitFilePreInvalidate(void)
bool RelationIdIsInInitFile(Oid relationId)
void RelationCacheInvalidateEntry(Oid relationId)
static void AssertCouldGetRelation(void)
void RelationMapInvalidate(bool shared)
char * GetDatabasePath(Oid dbOid, Oid spcOid)
void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n)
void ReceiveSharedInvalidMessages(void(*invalFunction)(SharedInvalidationMessage *msg), void(*resetFunction)(void))
#define SHAREDINVALCATALOG_ID
#define SHAREDINVALRELSYNC_ID
#define SHAREDINVALSMGR_ID
#define SHAREDINVALSNAPSHOT_ID
#define SHAREDINVALRELCACHE_ID
#define SHAREDINVALRELMAP_ID
void smgrreleaserellocator(RelFileLocatorBackend rlocator)
void InvalidateCatalogSnapshot(void)
SharedInvalidationMessage * msgs
bool RelcacheInitFileInval
InvalidationMsgsGroup CurrentCmdInvalidMsgs
RelcacheCallbackFunction function
RelSyncCallbackFunction function
SyscacheCallbackFunction function
struct TransInvalidationInfo * parent
struct InvalidationInfo ii
InvalidationMsgsGroup PriorCmdInvalidMsgs
void SysCacheInvalidate(int cacheId, uint32 hashValue)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
bool RelationInvalidatesSnapshotsOnly(Oid relid)
SharedInvalCatcacheMsg cc
SharedInvalRelcacheMsg rc
SharedInvalCatalogMsg cat
SharedInvalSnapshotMsg sn
int GetCurrentTransactionNestLevel(void)
bool IsTransactionState(void)
CommandId GetCurrentCommandId(bool used)
#define MinSizeOfXactInvals
#define XLOG_XACT_INVALIDATIONS
#define XLogLogicalInfoActive()
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterData(const void *data, uint32 len)
void XLogBeginInsert(void)