aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/cache/inval.c5
-rw-r--r--src/backend/utils/cache/relcache.c58
-rw-r--r--src/include/utils/relcache.h1
3 files changed, 53 insertions, 11 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 730a2949214..587a2cd248b 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -509,11 +509,8 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId)
/*
* If the relation being invalidated is one of those cached in the local
* relcache init file, mark that we need to zap that file at commit.
- * (Note: perhaps it would be better if this code were a bit more
- * decoupled from the knowledge that the init file contains exactly those
- * non-shared rels used in catalog caches.)
*/
- if (OidIsValid(dbId) && RelationSupportsSysCache(relId))
+ if (OidIsValid(dbId) && RelationIdIsInInitFile(relId))
transInvalInfo->RelcacheInitFileInval = true;
}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index a5521ca40a4..44e95098acb 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4879,21 +4879,32 @@ load_relcache_init_file(bool shared)
}
/*
- * We reached the end of the init file without apparent problem. Did we
- * get the right number of nailed items? (This is a useful crosscheck in
- * case the set of critical rels or indexes changes.)
+ * We reached the end of the init file without apparent problem. Did we
+ * get the right number of nailed items? This is a useful crosscheck in
+ * case the set of critical rels or indexes changes. However, that should
+ * not happen in a normally-running system, so let's bleat if it does.
*/
if (shared)
{
if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
+ {
+ elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
+ nailed_rels, nailed_indexes,
+ NUM_CRITICAL_SHARED_RELS, NUM_CRITICAL_SHARED_INDEXES);
goto read_failed;
+ }
}
else
{
if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
+ {
+ elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
+ nailed_rels, nailed_indexes,
+ NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_LOCAL_INDEXES);
goto read_failed;
+ }
}
/*
@@ -5011,12 +5022,19 @@ write_relcache_init_file(bool shared)
/*
* Ignore if not supposed to be in init file. We can allow any shared
* relation that's been loaded so far to be in the shared init file,
- * but unshared relations must be used for catalog caches. (Note: if
- * you want to change the criterion for rels to be kept in the init
- * file, see also inval.c.)
+ * but unshared relations must be ones that should be in the local
+ * file per RelationIdIsInInitFile. (Note: if you want to change the
+ * criterion for rels to be kept in the init file, see also inval.c.
+ * The reason for filtering here is to be sure that we don't put
+ * anything into the local init file for which a relcache inval would
+ * not cause invalidation of that init file.)
*/
- if (!shared && !RelationSupportsSysCache(RelationGetRelid(rel)))
+ if (!shared && !RelationIdIsInInitFile(RelationGetRelid(rel)))
+ {
+ /* Nailed rels had better get stored. */
+ Assert(!rel->rd_isnailed);
continue;
+ }
/* first write the relcache entry proper */
write_item(rel, sizeof(RelationData), fp);
@@ -5133,6 +5151,32 @@ write_item(const void *data, Size len, FILE *fp)
}
/*
+ * Determine whether a given relation (identified by OID) is one of the ones
+ * we should store in the local relcache init file.
+ *
+ * We must cache all nailed rels, and for efficiency we should cache every rel
+ * that supports a syscache. The former set is almost but not quite a subset
+ * of the latter. Currently, we must special-case TriggerRelidNameIndexId,
+ * which RelationCacheInitializePhase3 chooses to nail for efficiency reasons,
+ * but which does not support any syscache.
+ *
+ * Note: this function is currently never called for shared rels. If it were,
+ * we'd probably also need a special case for DatabaseNameIndexId, which is
+ * critical but does not support a syscache.
+ */
+bool
+RelationIdIsInInitFile(Oid relationId)
+{
+ if (relationId == TriggerRelidNameIndexId)
+ {
+ /* If this Assert fails, we don't need this special case anymore. */
+ Assert(!RelationSupportsSysCache(relationId));
+ return true;
+ }
+ return RelationSupportsSysCache(relationId);
+}
+
+/*
* Invalidate (remove) the init file during commit of a transaction that
* changed one or more of the relation cache entries that are kept in the
* local init file.
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 9bea572f2ca..6953281b741 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -116,6 +116,7 @@ extern void AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid,
/*
* Routines to help manage rebuilding of relcache init files
*/
+extern bool RelationIdIsInInitFile(Oid relationId);
extern void RelationCacheInitFilePreInvalidate(void);
extern void RelationCacheInitFilePostInvalidate(void);
extern void RelationCacheInitFileRemove(void);