3737#include "utils/memutils.h"
3838#include "catalog/gp_id.h"
3939#include "catalog/indexing.h"
40+ #include "catalog/heap.h"
4041#include "cdb/cdbhash.h"
4142#include "cdb/cdbutil.h"
4243#include "cdb/cdbmotion.h"
6061#include "catalog/gp_indexing.h"
6162#include "utils/etcd.h"
6263#include "common/etcdutils.h"
64+ #include "storage/sinvaladt.h"
65+ #include "storage/bufmgr.h"
66+ #include "utils/syscache.h"
6367
6468#include "catalog/gp_indexing.h"
6569
7983
8084MemoryContext CdbComponentsContext = NULL ;
8185static CdbComponentDatabases * cdb_component_dbs = NULL ;
86+ char * gp_segment_configuration_file = NULL ;
8287
8388#ifdef USE_INTERNAL_FTS
8489
@@ -92,6 +97,7 @@ static int CdbComponentDatabaseInfoCompare(const void *p1, const void *p2);
9297
9398static GpSegConfigEntry * readGpSegConfigFromCatalog (int * total_dbs );
9499static GpSegConfigEntry * readGpSegConfigFromFTSFiles (int * total_dbs );
100+ static GpSegConfigEntry * readGpSegConfigFromExtFile (int * total_dbs );
95101
96102static void getAddressesForDBid (GpSegConfigEntry * c , int elevel );
97103static HTAB * hostPrimaryCountHashTableInit (void );
@@ -372,7 +378,14 @@ getCdbComponentInfo(void)
372378
373379 HTAB * hostPrimaryCountHash = hostPrimaryCountHashTableInit ();
374380
375- if (IsTransactionState ())
381+ /* On hotstandby, if gp_segment_configuration_file is configured, try
382+ * to load configs from it. Since hotstandby may be created from a
383+ * basebackup that the table gp_segment_configuration is backuped from
384+ * the souce cluster and cannot be modified in read repilca mode.
385+ */
386+ if (EnableHotStandby && gp_segment_configuration_file )
387+ configs = readGpSegConfigFromExtFile (& total_dbs );
388+ else if (IsTransactionState ())
376389 configs = readGpSegConfigFromCatalog (& total_dbs );
377390 else
378391 configs = readGpSegConfigFromFTSFiles (& total_dbs );
@@ -1998,7 +2011,172 @@ gp_get_suboverflowed_backends(PG_FUNCTION_ARGS)
19982011 PG_RETURN_NULL ();
19992012}
20002013
2001- #else
2014+ void
2015+ add_segment_config_entry (GpSegConfigEntry * i )
2016+ {
2017+ Relation rel = table_open (GpSegmentConfigRelationId , AccessExclusiveLock );
2018+ Datum values [Natts_gp_segment_configuration ];
2019+ bool nulls [Natts_gp_segment_configuration ];
2020+ HeapTuple tuple ;
2021+
2022+ MemSet (nulls , false, sizeof (nulls ));
2023+
2024+ values [Anum_gp_segment_configuration_dbid - 1 ] = Int16GetDatum (i -> dbid );
2025+ values [Anum_gp_segment_configuration_content - 1 ] = Int16GetDatum (i -> segindex );
2026+ values [Anum_gp_segment_configuration_role - 1 ] = CharGetDatum (i -> role );
2027+ values [Anum_gp_segment_configuration_preferred_role - 1 ] =
2028+ CharGetDatum (i -> preferred_role );
2029+ values [Anum_gp_segment_configuration_mode - 1 ] =
2030+ CharGetDatum (i -> mode );
2031+ values [Anum_gp_segment_configuration_status - 1 ] =
2032+ CharGetDatum (i -> status );
2033+ values [Anum_gp_segment_configuration_port - 1 ] =
2034+ Int32GetDatum (i -> port );
2035+ values [Anum_gp_segment_configuration_hostname - 1 ] =
2036+ CStringGetTextDatum (i -> hostname );
2037+ values [Anum_gp_segment_configuration_address - 1 ] =
2038+ CStringGetTextDatum (i -> address );
2039+ values [Anum_gp_segment_configuration_datadir - 1 ] =
2040+ CStringGetTextDatum (i -> datadir );
2041+ values [Anum_gp_segment_configuration_warehouseid - 1 ] =
2042+ ObjectIdGetDatum (i -> warehouseid );
2043+
2044+ tuple = heap_form_tuple (RelationGetDescr (rel ), values , nulls );
2045+
2046+ /* insert a new tuple */
2047+ CatalogTupleInsert (rel , tuple );
2048+
2049+ table_close (rel , NoLock );
2050+ }
2051+
2052+ void
2053+ remove_segment_config_entry (int16 dbid )
2054+ {
2055+ int numDel = 0 ;
2056+ ScanKeyData scankey ;
2057+ SysScanDesc sscan ;
2058+ HeapTuple tuple ;
2059+ Relation rel ;
2060+
2061+ rel = table_open (GpSegmentConfigRelationId , RowExclusiveLock );
2062+
2063+ ScanKeyInit (& scankey ,
2064+ Anum_gp_segment_configuration_dbid ,
2065+ BTEqualStrategyNumber , F_INT2EQ ,
2066+ Int16GetDatum (dbid ));
2067+ sscan = systable_beginscan (rel , GpSegmentConfigDbidWarehouseIndexId , true,
2068+ NULL , 1 , & scankey );
2069+ while ((tuple = systable_getnext (sscan )) != NULL )
2070+ {
2071+ Datum attr ;
2072+ bool isNull ;
2073+ Oid warehouseid = InvalidOid ;
2074+
2075+ attr = heap_getattr (tuple , Anum_gp_segment_configuration_warehouseid ,
2076+ RelationGetDescr (rel ), & isNull );
2077+ Assert (!isNull );
2078+ warehouseid = DatumGetObjectId (attr );
2079+
2080+ if (!OidIsValid (warehouseid ) || warehouseid == GetCurrentWarehouseId ())
2081+ {
2082+ CatalogTupleDelete (rel , & tuple -> t_self );
2083+ numDel ++ ;
2084+ }
2085+ }
2086+ systable_endscan (sscan );
2087+
2088+ Assert (numDel > 0 );
2089+
2090+ table_close (rel , NoLock );
2091+ }
2092+
2093+ static GpSegConfigEntry *
2094+ readGpSegConfigFromExtFile (int * total_dbs )
2095+ {
2096+ FILE * fd ;
2097+ int idx = 0 ;
2098+ int array_size = 500 ;
2099+ GpSegConfigEntry * configs = NULL ;
2100+ GpSegConfigEntry * config = NULL ;
2101+
2102+ char hostname [MAXHOSTNAMELEN ];
2103+ char address [MAXHOSTNAMELEN ];
2104+ char datadir [1000 ];
2105+ char buf [MAXHOSTNAMELEN * 2 + 32 + 2000 ];
2106+
2107+ Assert (gp_segment_configuration_file && strcmp (gp_segment_configuration_file , "" ) != 0 );
2108+
2109+ /* notify and wait FTS to finish a probe and update the dump file */
2110+
2111+ fd = AllocateFile (gp_segment_configuration_file , "r" );
2112+
2113+ if (!fd )
2114+ elog (ERROR , "could not open gp_segment_configutation dump file:%s:%m" , gp_segment_configuration_file );
2115+
2116+ configs = palloc0 (sizeof (GpSegConfigEntry ) * array_size );
2117+ while (fgets (buf , sizeof (buf ), fd ))
2118+ {
2119+ config = & configs [idx ];
2120+
2121+ if (sscanf (buf , "%d %d %c %c %c %c %d %s %s %s" , (int * )& config -> dbid , (int * )& config -> segindex ,
2122+ & config -> role , & config -> preferred_role , & config -> mode , & config -> status ,
2123+ & config -> port , hostname , address , datadir ) != 10 )
2124+ {
2125+ FreeFile (fd );
2126+ elog (ERROR , "invalid data in gp_segment_configuration dump file: %s:%m" , gp_segment_configuration_file );
2127+ }
2128+
2129+ config -> hostname = pstrdup (hostname );
2130+ config -> address = pstrdup (address );
2131+ config -> datadir = pstrdup (datadir );
2132+
2133+ idx ++ ;
2134+ /*
2135+ * Expand CdbComponentDatabaseInfo array if we've used up
2136+ * currently allocated space
2137+ */
2138+ if (idx >= array_size )
2139+ {
2140+ array_size = array_size * 2 ;
2141+ configs = (GpSegConfigEntry * )
2142+ repalloc (configs , sizeof (GpSegConfigEntry ) * array_size );
2143+ }
2144+ }
2145+
2146+ FreeFile (fd );
2147+
2148+ * total_dbs = idx ;
2149+ return configs ;
2150+ }
2151+
2152+ void
2153+ write_gp_segment_configuration (void )
2154+ {
2155+ Relation rel ;
2156+ GpSegConfigEntry * configs ;
2157+ int total_dbs ;
2158+ SysScanDesc sscan ;
2159+ HeapTuple tuple ;
2160+
2161+ rel = table_open (GpSegmentConfigRelationId , RowExclusiveLock );
2162+ sscan = systable_beginscan (rel , GpSegmentConfigDbidWarehouseIndexId , true,
2163+ NULL , 0 , NULL );
2164+ while ((tuple = systable_getnext (sscan )) != NULL )
2165+ {
2166+ CatalogTupleDelete (rel , & tuple -> t_self );
2167+ }
2168+ systable_endscan (sscan );
2169+
2170+ /* insert new configs into gp_segment_configuration table */
2171+ configs = readGpSegConfigFromExtFile (& total_dbs );
2172+ for (int i = 0 ; i < total_dbs ; i ++ ) {
2173+ GpSegConfigEntry config = configs [i ];
2174+ add_segment_config_entry (& config );
2175+ }
2176+ table_close (rel , RowExclusiveLock );
2177+ }
2178+
2179+ #else
20022180bool am_ftshandler = false;
20032181
20042182
0 commit comments