From 46287bd6602ea055e2099426550a4bfafab8ed6f Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 4 May 2006 18:51:36 +0000 Subject: [PATCH] Simplify relcache startup sequence. With the new design of InitPostgres it's not necessary to have three separate calls anymore. This patch also fixes things so we don't try to read pg_internal.init until after we've obtained lock on the target database; which was fairly harmless, but it's certainly cleaner this way. --- src/backend/utils/cache/relcache.c | 78 ++++++++++++++++-------------- src/backend/utils/init/postinit.c | 23 +++------ src/include/utils/relcache.h | 3 +- 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 878678be75..75c26f0435 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.239 2006/04/25 22:46:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.240 2006/05/04 18:51:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2156,10 +2156,11 @@ RelationBuildLocalRelation(const char *relname, * * This initializes the relation descriptor cache. At the time * that this is invoked, we can't do database access yet (mainly - * because the transaction subsystem is not up), so we can't get - * "real" info. However it's okay to read the pg_internal.init - * cache file, if one is available. Otherwise we make phony - * entries for the minimum set of nailed-in-cache relations. + * because the transaction subsystem is not up); all we are doing + * is making an empty cache hashtable. This must be done before + * starting the initialization transaction, because otherwise + * AtEOXact_RelationCache would crash if that transaction aborts + * before we can get the relcache set up. */ #define INITRELCACHESIZE 400 @@ -2188,10 +2189,38 @@ RelationCacheInitialize(void) RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE, &ctl, HASH_ELEM | HASH_FUNCTION); + MemoryContextSwitchTo(oldcxt); +} + +/* + * RelationCacheInitializePhase2 + * + * This is called as soon as the catcache and transaction system + * are functional. At this point we can actually read data from + * the system catalogs. We first try to read pre-computed relcache + * entries from the pg_internal.init file. If that's missing or + * broken, make phony entries for the minimum set of nailed-in-cache + * relations. Then (unless bootstrapping) make sure we have entries + * for the critical system indexes. Once we've done all this, we + * have enough infrastructure to open any system catalog or use any + * catcache. The last step is to rewrite pg_internal.init if needed. + */ +void +RelationCacheInitializePhase2(void) +{ + HASH_SEQ_STATUS status; + RelIdCacheEnt *idhentry; + MemoryContext oldcxt; + /* - * Try to load the relcache cache file. If successful, we're done for - * now. Otherwise, initialize the cache with pre-made descriptors for the - * critical "nailed-in" system catalogs. + * switch to cache memory context + */ + oldcxt = MemoryContextSwitchTo(CacheMemoryContext); + + /* + * Try to load the relcache cache file. If unsuccessful, bootstrap the + * cache with pre-made descriptors for the critical "nailed-in" system + * catalogs. */ if (IsBootstrapProcessingMode() || !load_relcache_init_file()) @@ -2209,23 +2238,8 @@ RelationCacheInitialize(void) } MemoryContextSwitchTo(oldcxt); -} - -/* - * RelationCacheInitializePhase2 - * - * This is called as soon as the catcache and transaction system - * are functional. At this point we can actually read data from - * the system catalogs. Update the relcache entries made during - * RelationCacheInitialize, and make sure we have entries for the - * critical system indexes. - */ -void -RelationCacheInitializePhase2(void) -{ - HASH_SEQ_STATUS status; - RelIdCacheEnt *idhentry; + /* In bootstrap mode, the faked-up formrdesc info is all we'll have */ if (IsBootstrapProcessingMode()) return; @@ -2334,20 +2348,10 @@ RelationCacheInitializePhase2(void) if (relation->rd_rel->reltriggers > 0 && relation->trigdesc == NULL) RelationBuildTriggers(relation); } -} - -/* - * RelationCacheInitializePhase3 - * - * Final step of relcache initialization: write out a new relcache - * cache file if one is needed. - */ -void -RelationCacheInitializePhase3(void) -{ - if (IsBootstrapProcessingMode()) - return; + /* + * Lastly, write out a new relcache cache file if one is needed. + */ if (needNewCacheFile) { /* diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 0be0fd8543..5294cf0040 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.166 2006/05/04 16:07:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.167 2006/05/04 18:51:36 tgl Exp $ * * *------------------------------------------------------------------------- @@ -357,16 +357,12 @@ InitPostgres(const char *dbname, const char *username) InitXLOGAccess(); /* - * Initialize the relation descriptor cache. This must create at least - * the minimum set of "nailed-in" cache entries. No catalog access - * happens here. + * Initialize the relation cache and the system catalog caches. Note that + * no catalog access happens here; we only set up the hashtable structure. + * We must do this before starting a transaction because transaction + * abort would try to touch these hashtables. */ RelationCacheInitialize(); - - /* - * Initialize all the system catalog caches. Note that no catalog access - * happens here; we only set up the cache structure. - */ InitCatalogCache(); /* Initialize portal manager */ @@ -458,7 +454,8 @@ InitPostgres(const char *dbname, const char *username) /* * It's now possible to do real access to the system catalogs. * - * Replace faked-up relcache entries with correct info. + * Load relcache entries for the system catalogs. This must create at + * least the minimum set of "nailed-in" cache entries. */ RelationCacheInitializePhase2(); @@ -503,12 +500,6 @@ InitPostgres(const char *dbname, const char *username) if (!bootstrap) CheckMyDatabase(dbname, am_superuser); - /* - * Final phase of relation cache startup: write a new cache file if - * necessary. (XXX this could be folded back into Phase2) - */ - RelationCacheInitializePhase3(); - /* * Check a normal user hasn't connected to a superuser reserved slot. */ diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index d9a355af24..b30387a7ef 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.53 2006/03/05 15:59:07 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.54 2006/05/04 18:51:36 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,7 +44,6 @@ extern void RelationInitIndexAccessInfo(Relation relation); */ extern void RelationCacheInitialize(void); extern void RelationCacheInitializePhase2(void); -extern void RelationCacheInitializePhase3(void); /* * Routine to create a relcache entry for an about-to-be-created relation