Skip to content

Commit f487866

Browse files
committed
Add guc gp_segment_configuration_file
For hot_standby which is built on basebackup data, the gp_segment_configuration table is copied from primary cluster and cannot be used by standby cluster. To fix that, add the guc gp_segment_configuration_file to load the standby cluster's segment info. It will be used by gpstart and getCdbComponentInfo when doing read only queries. TODO: gpstart starting with param -f to load the gp_segment_configuration from file is not finished yet.
1 parent ef81bbf commit f487866

File tree

7 files changed

+201
-78
lines changed

7 files changed

+201
-78
lines changed

gpMgmt/bin/gpstart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ class GpStart:
511511
logger.info("Obtaining Segment details from coordinator...")
512512
self.dburl = dbconn.DbURL(port=self.port, dbname='template1')
513513
self.gparray = GpArray.initFromCatalog(self.dburl, utility=True)
514+
## standby cluster load gp_segment_configuration from file.
515+
#self.gparray = GpArray.initFromFile("/usr/local/gpdr/gpdr_gp_segment_configuration_1")
516+
#self.gparray.is_singlenode= False
514517

515518
logger.info("Setting new coordinator era")
516519
e = GpEraFile(self.coordinator_datadir, logger=get_logger_if_verbose())

src/backend/access/transam/xlog.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6629,6 +6629,7 @@ UpdateCatalogForStandbyPromotion(void)
66296629
/* I am privileged */
66306630
InitializeSessionUserIdStandalone();
66316631
gp_activate_standby();
6632+
write_gp_segment_configuration();
66326633
/* close the transaction we started above */
66336634
CommitTransactionCommand();
66346635
Gp_role = old_role;

src/backend/cdb/cdbutil.c

Lines changed: 180 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
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"
@@ -60,6 +61,9 @@
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

@@ -79,6 +83,7 @@
7983

8084
MemoryContext CdbComponentsContext = NULL;
8185
static 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

9398
static GpSegConfigEntry * readGpSegConfigFromCatalog(int *total_dbs);
9499
static GpSegConfigEntry * readGpSegConfigFromFTSFiles(int *total_dbs);
100+
static GpSegConfigEntry * readGpSegConfigFromExtFile(int *total_dbs);
95101

96102
static void getAddressesForDBid(GpSegConfigEntry *c, int elevel);
97103
static 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
20022180
bool am_ftshandler = false;
20032181

20042182

src/backend/utils/gp/segadmin.c

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -181,87 +181,12 @@ static void
181181
remove_segment_config(int16 dbid)
182182
{
183183
#ifdef USE_INTERNAL_FTS
184-
int numDel = 0;
185-
ScanKeyData scankey;
186-
SysScanDesc sscan;
187-
HeapTuple tuple;
188-
Relation rel;
189-
190-
rel = table_open(GpSegmentConfigRelationId, RowExclusiveLock);
191-
192-
ScanKeyInit(&scankey,
193-
Anum_gp_segment_configuration_dbid,
194-
BTEqualStrategyNumber, F_INT2EQ,
195-
Int16GetDatum(dbid));
196-
sscan = systable_beginscan(rel, GpSegmentConfigDbidWarehouseIndexId, true,
197-
NULL, 1, &scankey);
198-
while ((tuple = systable_getnext(sscan)) != NULL)
199-
{
200-
Datum attr;
201-
bool isNull;
202-
Oid warehouseid = InvalidOid;
203-
204-
attr = heap_getattr(tuple, Anum_gp_segment_configuration_warehouseid,
205-
RelationGetDescr(rel), &isNull);
206-
Assert(!isNull);
207-
warehouseid = DatumGetObjectId(attr);
208-
209-
if (!OidIsValid(warehouseid) || warehouseid == GetCurrentWarehouseId())
210-
{
211-
CatalogTupleDelete(rel, &tuple->t_self);
212-
numDel++;
213-
}
214-
}
215-
systable_endscan(sscan);
216-
217-
Assert(numDel > 0);
218-
219-
table_close(rel, NoLock);
184+
remove_segment_config_entry(dbid);
220185
#else
221186
delSegment(dbid);
222187
#endif
223188
}
224189

225-
#ifdef USE_INTERNAL_FTS
226-
static void
227-
add_segment_config_entry(GpSegConfigEntry *i)
228-
{
229-
Relation rel = table_open(GpSegmentConfigRelationId, AccessExclusiveLock);
230-
Datum values[Natts_gp_segment_configuration];
231-
bool nulls[Natts_gp_segment_configuration];
232-
HeapTuple tuple;
233-
234-
MemSet(nulls, false, sizeof(nulls));
235-
236-
values[Anum_gp_segment_configuration_dbid - 1] = Int16GetDatum(i->dbid);
237-
values[Anum_gp_segment_configuration_content - 1] = Int16GetDatum(i->segindex);
238-
values[Anum_gp_segment_configuration_role - 1] = CharGetDatum(i->role);
239-
values[Anum_gp_segment_configuration_preferred_role - 1] =
240-
CharGetDatum(i->preferred_role);
241-
values[Anum_gp_segment_configuration_mode - 1] =
242-
CharGetDatum(i->mode);
243-
values[Anum_gp_segment_configuration_status - 1] =
244-
CharGetDatum(i->status);
245-
values[Anum_gp_segment_configuration_port - 1] =
246-
Int32GetDatum(i->port);
247-
values[Anum_gp_segment_configuration_hostname - 1] =
248-
CStringGetTextDatum(i->hostname);
249-
values[Anum_gp_segment_configuration_address - 1] =
250-
CStringGetTextDatum(i->address);
251-
values[Anum_gp_segment_configuration_datadir - 1] =
252-
CStringGetTextDatum(i->datadir);
253-
values[Anum_gp_segment_configuration_warehouseid - 1] =
254-
ObjectIdGetDatum(i->warehouseid);
255-
256-
tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
257-
258-
/* insert a new tuple */
259-
CatalogTupleInsert(rel, tuple);
260-
261-
table_close(rel, NoLock);
262-
}
263-
#endif
264-
265190
static void
266191
add_segment(GpSegConfigEntry *new_segment_information)
267192
{

src/backend/utils/misc/guc_gp.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5029,6 +5029,16 @@ struct config_string ConfigureNamesString_gp[] =
50295029
"",
50305030
NULL, NULL, NULL
50315031
},
5032+
{
5033+
{"gp_segment_configuration_file", PGC_SUSET, DEVELOPER_OPTIONS,
5034+
gettext_noop("Specifies the recovery cluster gp_segment_configuration file"),
5035+
gettext_noop(""),
5036+
GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
5037+
},
5038+
&gp_segment_configuration_file,
5039+
"",
5040+
NULL, NULL, NULL
5041+
},
50325042

50335043
/* End-of-list marker */
50345044
{

src/include/cdb/cdbutil.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ extern char *gp_etcd_cluster_id;
3737
extern char *gp_etcd_namespace;
3838
extern char *gp_etcd_endpoints;
3939

40+
extern char *gp_segment_configuration_file;
41+
4042
typedef struct GpSegConfigEntryForUDF
4143
{
4244
GpSegConfigEntry * config_entry;
@@ -132,6 +134,9 @@ extern char *getDnsAddress(char *name, int port, int elevel);
132134

133135
#ifdef USE_INTERNAL_FTS
134136
extern void writeGpSegConfigToFTSFiles(void);
137+
extern void add_segment_config_entry(GpSegConfigEntry *i);
138+
extern void remove_segment_config_entry(int16 dbid);
139+
extern void write_gp_segment_configuration(void);
135140
#else
136141

137142
GpSegConfigEntry * readGpSegConfig(char * buff, int *total_dbs);

src/include/utils/unsync_guc_name.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@
241241
"gp_max_slices",
242242
"gp_motion_cost_per_row",
243243
"gp_pause_on_restore_point_replay",
244+
"gp_segment_configuration_file",
244245
"gp_predicate_pushdown_sample_rows",
245246
"gp_print_create_gang_time",
246247
"gp_qd_hostname",

0 commit comments

Comments
 (0)