/* * Populate cdb_component_dbs object by reading from catalog. Use * probeContext instead of current memory context because current * context will be destroyed by CommitTransactionCommand(). */ static void readCdbComponentInfoAndUpdateStatus(MemoryContext probeContext) { int i; MemoryContext save = MemoryContextSwitchTo(probeContext); /* cdb_component_dbs is free'd by FtsLoop(). */ cdb_component_dbs = getCdbComponentInfo(false); MemoryContextSwitchTo(save); for (i=0; i < cdb_component_dbs->total_segment_dbs; i++) { CdbComponentDatabaseInfo *segInfo = &cdb_component_dbs->segment_db_info[i]; uint8 segStatus; segStatus = 0; if (SEGMENT_IS_ALIVE(segInfo)) segStatus |= FTS_STATUS_ALIVE; if (SEGMENT_IS_ACTIVE_PRIMARY(segInfo)) segStatus |= FTS_STATUS_PRIMARY; if (segInfo->preferred_role == 'p') segStatus |= FTS_STATUS_DEFINEDPRIMARY; if (segInfo->mode == 's') segStatus |= FTS_STATUS_SYNCHRONIZED; if (segInfo->mode == 'c') segStatus |= FTS_STATUS_CHANGELOGGING; ftsProbeInfo->fts_status[segInfo->dbid] = segStatus; } }
static int CdbComponentDatabaseInfoCompare(const void *p1, const void *p2) { const CdbComponentDatabaseInfo *obj1 = (CdbComponentDatabaseInfo *) p1; const CdbComponentDatabaseInfo *obj2 = (CdbComponentDatabaseInfo *) p2; int cmp = obj1->segindex - obj2->segindex; if (cmp == 0) { int obj2cmp=0; int obj1cmp=0; if (SEGMENT_IS_ACTIVE_PRIMARY(obj2)) obj2cmp = 1; if (SEGMENT_IS_ACTIVE_PRIMARY(obj1)) obj1cmp = 1; cmp = obj2cmp - obj1cmp; } return cmp; }
bool FtsIsSegmentAlive(CdbComponentDatabaseInfo *segInfo) { switch (failover_strategy) { case 'f': if (SEGMENT_IS_ACTIVE_MIRROR(segInfo) && SEGMENT_IS_ALIVE(segInfo)) return true; /* fallthrough */ case 'n': case 's': if (SEGMENT_IS_ACTIVE_PRIMARY(segInfo)) return true; break; default: write_log("segmentToProbe: invalid failover strategy (%c).", failover_strategy); break; } return false; }
/* * Reads the GP catalog tables and build a CdbComponentDatabases structure. * It then converts this to a Gang structure and initializes all the non-connection related fields. * * Call this function in GangContext. * Returns a not-null pointer. */ Gang * buildGangDefinition(GangType type, int gang_id, int size, int content) { Gang *newGangDefinition = NULL; CdbComponentDatabaseInfo *cdbinfo = NULL; CdbComponentDatabaseInfo *cdbInfoCopy = NULL; SegmentDatabaseDescriptor *segdbDesc = NULL; MemoryContext perGangContext = NULL; int segCount = 0; int i = 0; ELOG_DISPATCHER_DEBUG("buildGangDefinition:Starting %d qExec processes for %s gang", size, gangTypeToString(type)); Assert(CurrentMemoryContext == GangContext); Assert(size == 1 || size == getgpsegmentCount()); /* read gp_segment_configuration and build CdbComponentDatabases */ cdb_component_dbs = getComponentDatabases(); if (cdb_component_dbs == NULL || cdb_component_dbs->total_segments <= 0 || cdb_component_dbs->total_segment_dbs <= 0) insist_log(false, "schema not populated while building segworker group"); /* if mirroring is not configured */ if (cdb_component_dbs->total_segment_dbs == cdb_component_dbs->total_segments) { ELOG_DISPATCHER_DEBUG("building Gang: mirroring not configured"); disableFTS(); } perGangContext = AllocSetContextCreate(GangContext, "Per Gang Context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); Assert(perGangContext != NULL); MemoryContextSwitchTo(perGangContext); /* allocate a gang */ newGangDefinition = (Gang *) palloc0(sizeof(Gang)); newGangDefinition->type = type; newGangDefinition->size = size; newGangDefinition->gang_id = gang_id; newGangDefinition->allocated = false; newGangDefinition->noReuse = false; newGangDefinition->dispatcherActive = false; newGangDefinition->portal_name = NULL; newGangDefinition->perGangContext = perGangContext; newGangDefinition->db_descriptors = (SegmentDatabaseDescriptor *) palloc0(size * sizeof(SegmentDatabaseDescriptor)); /* initialize db_descriptors */ switch (type) { case GANGTYPE_ENTRYDB_READER: cdbinfo = &cdb_component_dbs->entry_db_info[0]; cdbInfoCopy = copyCdbComponentDatabaseInfo(cdbinfo); segdbDesc = &newGangDefinition->db_descriptors[0]; cdbconn_initSegmentDescriptor(segdbDesc, cdbInfoCopy); setQEIdentifier(segdbDesc, -1, perGangContext); break; case GANGTYPE_SINGLETON_READER: cdbinfo = findDatabaseInfoBySegIndex(cdb_component_dbs, content); cdbInfoCopy = copyCdbComponentDatabaseInfo(cdbinfo); segdbDesc = &newGangDefinition->db_descriptors[0]; cdbconn_initSegmentDescriptor(segdbDesc, cdbInfoCopy); setQEIdentifier(segdbDesc, -1, perGangContext); break; case GANGTYPE_PRIMARY_READER: case GANGTYPE_PRIMARY_WRITER: /* * We loop through the segment_db_info. Each item has a segindex. * They are sorted by segindex, and there can be > 1 segment_db_info for * a given segindex (currently, there can be 1 or 2) */ for (i = 0; i < cdb_component_dbs->total_segment_dbs; i++) { cdbinfo = &cdb_component_dbs->segment_db_info[i]; if (SEGMENT_IS_ACTIVE_PRIMARY(cdbinfo)) { segdbDesc = &newGangDefinition->db_descriptors[segCount]; cdbInfoCopy = copyCdbComponentDatabaseInfo(cdbinfo); cdbconn_initSegmentDescriptor(segdbDesc, cdbInfoCopy); setQEIdentifier(segdbDesc, -1, perGangContext); segCount++; } } if (size != segCount) { FtsReConfigureMPP(false); elog(ERROR, "Not all primary segment instances are active and connected"); } break; default: Assert(false); } ELOG_DISPATCHER_DEBUG("buildGangDefinition done"); MemoryContextSwitchTo(GangContext); return newGangDefinition; }
/* * Build a set of changes, based on our current state, and the probe results. */ static bool probePublishUpdate(uint8 *probe_results) { bool update_found = false; int i; if (failover_strategy == 'f') { /* preprocess probe results to decide what is the current segment state */ FtsPreprocessProbeResultsFilerep(cdb_component_dbs, probe_results); } for (i = 0; i < cdb_component_dbs->total_segment_dbs; i++) { CdbComponentDatabaseInfo *segInfo = &cdb_component_dbs->segment_db_info[i]; /* if we've gotten a pause or shutdown request, we ignore our probe results. */ if (!FtsIsActive()) { return false; } /* we check segments in pairs of primary-mirror */ if (!SEGMENT_IS_ACTIVE_PRIMARY(segInfo)) { continue; } CdbComponentDatabaseInfo *primary = segInfo; CdbComponentDatabaseInfo *mirror = FtsGetPeerSegment(segInfo->segindex, segInfo->dbid); if (failover_strategy == 'n') { Assert(SEGMENT_IS_ACTIVE_PRIMARY(segInfo)); Assert(FTS_STATUS_ISALIVE(segInfo->dbid, ftsProbeInfo->fts_status)); Assert(mirror == NULL); /* no mirror available to failover */ if (!PROBE_IS_ALIVE(segInfo)) { FtsSegmentStatusChange changes; uint8 statusOld = ftsProbeInfo->fts_status[segInfo->dbid]; uint8 statusNew = statusOld & ~FTS_STATUS_ALIVE; buildSegmentStateChange(segInfo, &changes, statusNew); FtsFailoverNull(&changes); } continue; } Assert(failover_strategy == 'f' || failover_strategy == 's'); Assert(mirror != NULL); /* changes required for primary and mirror */ FtsSegmentStatusChange changes[2]; uint32 stateOld = 0; uint32 stateNew = 0; bool isPrimaryAlive = PROBE_IS_ALIVE(primary); bool isMirrorAlive = PROBE_IS_ALIVE(mirror); /* get transition type */ uint32 trans = getTransition(isPrimaryAlive, isMirrorAlive); if (gp_log_fts > GPVARS_VERBOSITY_VERBOSE) { elog(LOG, "FTS: primary found %s, mirror found %s, transition %d.", (isPrimaryAlive ? "alive" : "dead"), (isMirrorAlive ? "alive" : "dead"), trans); } if (trans == TRANS_D_D) { elog(LOG, "FTS: detected double failure for content=%d, primary (dbid=%d), mirror (dbid=%d).", primary->segindex, primary->dbid, mirror->dbid); } if (failover_strategy == 'f') { /* get current state */ stateOld = FtsGetPairStateFilerep(primary, mirror); /* get new state */ stateNew = transition(stateOld, trans, primary, mirror, &changes[0], &changes[1]); } else { Assert(failover_strategy == 's'); /* get current state */ stateOld = FtsGetPairStateSAN(primary, mirror); /* get new state */ stateNew = transition(stateOld, trans, primary, mirror, &changes[0], &changes[1]); } /* check if transition is required */ if (stateNew != stateOld) { update_found = true; updateConfiguration(changes, ARRAY_SIZE(changes)); } } if (gp_log_fts >= GPVARS_VERBOSITY_VERBOSE) { elog(LOG, "FTS: probe result processing is complete."); } return update_found; }