summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/cache/inval.c7
-rw-r--r--src/backend/utils/cache/relcache.c57
-rw-r--r--src/backend/utils/cache/syscache.c75
-rw-r--r--src/include/utils/relcache.h1
-rw-r--r--src/include/utils/syscache.h4
5 files changed, 96 insertions, 48 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 62c4369b171..7e4bef3c6ba 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -461,10 +461,13 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId)
(void) GetCurrentCommandId(true);
/*
- * If the relation being invalidated is one of those cached in the
+ * 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 (RelationIdIsInInitFile(relId))
+ if (OidIsValid(dbId) && RelationSupportsSysCache(relId))
transInvalInfo->RelcacheInitFileInval = true;
}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 296c0631ee1..f5e43d486f4 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -131,14 +131,6 @@ bool criticalSharedRelcachesBuilt = false;
static long relcacheInvalsReceived = 0L;
/*
- * This list remembers the OIDs of the non-shared relations cached in the
- * database's local relcache init file. Note that there is no corresponding
- * list for the shared relcache init file, for reasons explained in the
- * comments for RelationCacheInitFileRemove.
- */
-static List *initFileRelationIds = NIL;
-
-/*
* eoxact_list[] stores the OIDs of relations that (might) need AtEOXact
* cleanup work. This list intentionally has limited size; if it overflows,
* we fall back to scanning the whole hashtable. There is no value in a very
@@ -3190,9 +3182,6 @@ RelationCacheInitializePhase3(void)
*/
InitCatalogCachePhase2();
- /* reset initFileRelationIds list; we'll fill it during write */
- initFileRelationIds = NIL;
-
/* now write the files */
write_relcache_init_file(true);
write_relcache_init_file(false);
@@ -4477,10 +4466,6 @@ load_relcache_init_file(bool shared)
for (relno = 0; relno < num_rels; relno++)
{
RelationCacheInsert(rels[relno]);
- /* also make a list of their OIDs, for RelationIdIsInInitFile */
- if (!shared)
- initFileRelationIds = lcons_oid(RelationGetRelid(rels[relno]),
- initFileRelationIds);
}
pfree(rels);
@@ -4517,10 +4502,16 @@ write_relcache_init_file(bool shared)
int magic;
HASH_SEQ_STATUS status;
RelIdCacheEnt *idhentry;
- MemoryContext oldcxt;
int i;
/*
+ * If we have already received any relcache inval events, there's no
+ * chance of succeeding so we may as well skip the whole thing.
+ */
+ if (relcacheInvalsReceived != 0L)
+ return;
+
+ /*
* We must write a temporary file and rename it into place. Otherwise,
* another backend starting at about the same time might crash trying to
* read the partially-complete file.
@@ -4579,6 +4570,16 @@ write_relcache_init_file(bool shared)
if (relform->relisshared != shared)
continue;
+ /*
+ * 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.)
+ */
+ if (!shared && !RelationSupportsSysCache(RelationGetRelid(rel)))
+ continue;
+
/* first write the relcache entry proper */
write_item(rel, sizeof(RelationData), fp);
@@ -4635,15 +4636,6 @@ write_relcache_init_file(bool shared)
relform->relnatts * sizeof(int16),
fp);
}
-
- /* also make a list of their OIDs, for RelationIdIsInInitFile */
- if (!shared)
- {
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- initFileRelationIds = lcons_oid(RelationGetRelid(rel),
- initFileRelationIds);
- MemoryContextSwitchTo(oldcxt);
- }
}
if (FreeFile(fp))
@@ -4703,21 +4695,6 @@ write_item(const void *data, Size len, FILE *fp)
}
/*
- * Detect whether a given relation (identified by OID) is one of the ones
- * we store in the local relcache init file.
- *
- * Note that we effectively assume that all backends running in a database
- * would choose to store the same set of relations in the init file;
- * otherwise there are cases where we'd fail to detect the need for an init
- * file invalidation. This does not seem likely to be a problem in practice.
- */
-bool
-RelationIdIsInInitFile(Oid relationId)
-{
- return list_member_oid(initFileRelationIds, 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/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 9aa5ee5ac05..94fc568d6e7 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -791,11 +791,18 @@ static const struct cachedesc cacheinfo[] = {
}
};
-static CatCache *SysCache[
- lengthof(cacheinfo)];
-static int SysCacheSize = lengthof(cacheinfo);
+#define SysCacheSize ((int) lengthof(cacheinfo))
+
+static CatCache *SysCache[SysCacheSize];
+
static bool CacheInitialized = false;
+/* Sorted array of OIDs of tables and indexes used by caches */
+static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
+static int SysCacheSupportingRelOidSize;
+
+static int oid_compare(const void *a, const void *b);
+
/*
* InitCatalogCache - initialize the caches
@@ -809,10 +816,12 @@ void
InitCatalogCache(void)
{
int cacheId;
+ int i,
+ j;
Assert(!CacheInitialized);
- MemSet(SysCache, 0, sizeof(SysCache));
+ SysCacheSupportingRelOidSize = 0;
for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
{
@@ -825,7 +834,25 @@ InitCatalogCache(void)
if (!PointerIsValid(SysCache[cacheId]))
elog(ERROR, "could not initialize cache %u (%d)",
cacheinfo[cacheId].reloid, cacheId);
+ /* Accumulate data for OID lists, too */
+ SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
+ cacheinfo[cacheId].reloid;
+ SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
+ cacheinfo[cacheId].indoid;
+ }
+
+ Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
+
+ /* Sort and de-dup OID arrays, so we can use binary search. */
+ pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
+ sizeof(Oid), oid_compare);
+ for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
+ {
+ if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
+ SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
}
+ SysCacheSupportingRelOidSize = j + 1;
+
CacheInitialized = true;
}
@@ -1113,3 +1140,43 @@ SearchSysCacheList(int cacheId, int nkeys,
return SearchCatCacheList(SysCache[cacheId], nkeys,
key1, key2, key3, key4);
}
+
+/*
+ * Test whether a relation supports a system cache, ie it is either a
+ * cached table or the index used for a cache.
+ */
+bool
+RelationSupportsSysCache(Oid relid)
+{
+ int low = 0,
+ high = SysCacheSupportingRelOidSize - 1;
+
+ while (low <= high)
+ {
+ int middle = low + (high - low) / 2;
+
+ if (SysCacheSupportingRelOid[middle] == relid)
+ return true;
+ if (SysCacheSupportingRelOid[middle] < relid)
+ low = middle + 1;
+ else
+ high = middle - 1;
+ }
+
+ return false;
+}
+
+
+/*
+ * OID comparator for pg_qsort
+ */
+static int
+oid_compare(const void *a, const void *b)
+{
+ Oid oa = *((const Oid *) a);
+ Oid ob = *((const Oid *) b);
+
+ if (oa == ob)
+ return 0;
+ return (oa > ob) ? 1 : -1;
+}
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 39b98f2568e..49c84b8cea8 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -105,7 +105,6 @@ 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);
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index d1d8abe0a90..8dc00102bfe 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -18,7 +18,7 @@
#include "access/attnum.h"
#include "access/htup.h"
-/* we purposedly do not include utils/catcache.h here */
+/* we intentionally do not include utils/catcache.h here */
/*
* SysCache identifiers.
@@ -125,6 +125,8 @@ struct catclist;
extern struct catclist *SearchSysCacheList(int cacheId, int nkeys,
Datum key1, Datum key2, Datum key3, Datum key4);
+extern bool RelationSupportsSysCache(Oid relid);
+
/*
* The use of the macros below rather than direct calls to the corresponding
* functions is encouraged, as it insulates the caller from changes in the