diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index d8f76cb81871e78797f8993c47aead5353599e0c..cfcbb87970d5e83f5a0279ff682f4b7569e751f5 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6446,6 +6446,130 @@ XLogProcessCheckpointRecord(XLogRecord *rec, XLogRecPtr loc) } } +static void +UpdateCatalogForStandbyPromotion(void) +{ + /* + * NOTE: The following initialization logic was borrowed from ftsprobe. + */ + SetProcessingMode(InitProcessing); + + /* + * Create a resource owner to keep track of our resources (currently only + * buffer pins). + */ + CurrentResourceOwner = ResourceOwnerCreate(NULL, "Startup Pass 4"); + + /* + * NOTE: AuxiliaryProcessMain has already called: + * NOTE: BaseInit, + * NOTE: InitAuxiliaryProcess instead of InitProcess, and + * NOTE: InitBufferPoolBackend. + */ + + InitXLOGAccess(); + + SetProcessingMode(NormalProcessing); + + /* + * Add my PGPROC struct to the ProcArray. + * + * Once I have done this, I am visible to other backends! + */ + InitProcessPhase2(); + + /* + * Initialize my entry in the shared-invalidation manager's array of + * per-backend data. + * + * Sets up MyBackendId, a unique backend identifier. + */ + MyBackendId = InvalidBackendId; + + /* + * Though this is a startup process and currently no one sends invalidation + * messages concurrently, we set sendOnly = false, since we have relcaches. + */ + SharedInvalBackendInit(false); + + if (MyBackendId > MaxBackends || MyBackendId <= 0) + elog(FATAL, "bad backend id: %d", MyBackendId); + + /* + * bufmgr needs another initialization call too + */ + InitBufferPoolBackend(); + + /* heap access requires the rel-cache. + * + * Pass 2 uses heap API to insert/update/delete from persistent + * tables. In order to use the heap API, RelationDescriptor is + * required. In pass 2, persistent tables are accessed using + * DirectOpen API to obtain the RelationDescriptor. Hence, we + * don't need to load full relcache as in + * RelationCacheInitializePhase3(). + * + * However, there is cache invalidation logic within heap API + * needs basic data structures for catalog cache to be + * initialized. Hence, we need to do RelationCacheInitialize(), + * InitCatalogCache(), and RelationCacheInitializePhase2() + * before StartupXLOG_Pass2(). + * + * Pass 4 needs RelationCacheInitializePhase3() to do catalog + * validation, after xlog replay is complete. + */ + RelationCacheInitialize(); + InitCatalogCache(); + + /* + * It's now possible to do real access to the system catalogs. + * + * Load relcache entries for the system catalogs. This must create at + * least the minimum set of "nailed-in" cache entries. + */ + RelationCacheInitializePhase2(); + + char *fullpath; + + /* + * In order to access the catalog, we need a database, and a + * tablespace; our access to the heap is going to be slightly + * limited, so we'll just use some defaults. + */ + MyDatabaseId = TemplateDbOid; + MyDatabaseTableSpace = DEFAULTTABLESPACE_OID; + + /* + * Now we can mark our PGPROC entry with the database ID + * (We assume this is an atomic store so no lock is needed) + */ + MyProc->databaseId = MyDatabaseId; + + fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace); + + SetDatabasePath(fullpath); + + RelationCacheInitializePhase3(); + + /* + * Now, finally, update the catalog. + */ + GpRoleValue old_role = Gp_role; + + /* I am privileged */ + InitializeSessionUserIdStandalone(); + /* Start transaction locally */ + Gp_role = GP_ROLE_UTILITY; + StartTransactionCommand(); + GetTransactionSnapshot(); + DirectFunctionCall1(gp_activate_standby, (Datum) 0); + /* close the transaction we started above */ + CommitTransactionCommand(); + Gp_role = old_role; + + ereport(LOG, (errmsg("Updated catalog to support standby promotion"))); +} + static void UpdateCatalogForStandbyPromotion(void) @@ -7558,14 +7682,7 @@ StartupXLOG(void) true); #endif - /* - * If we are a standby with contentid -1 and undergoing promotion, - * update ourselves as the new master in catalog. This does not - * apply to a mirror (standby of a GPDB segment) because it is - * managed by FTS. - */ - bool needToPromoteCatalog = (GpIdentity.segindex == MASTER_CONTENT_ID && - ControlFile->state == DB_IN_STANDBY_PROMOTED); + bool needToPromoteCatalog = (ControlFile->state == DB_IN_STANDBY_PROMOTED); LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->state = DB_IN_PRODUCTION;