// Failover promotes replicas to primary for the remaining nodes. func Failover(cfg cbgt.Cfg, version string, server string, options map[string]string, nodesFailover []string) (bool, error) { mapNodesFailover := cbgt.StringsToMap(nodesFailover) uuid := "" indexDefs, nodeDefs, planPIndexesPrev, cas, err := cbgt.PlannerGetPlan(cfg, version, uuid) if err != nil { return false, err } planPIndexesCalc, err := cbgt.CalcPlan("failover", indexDefs, nodeDefs, planPIndexesPrev, version, server, options, nil) if err != nil { return false, fmt.Errorf("planner: failover CalcPlan, err: %v", err) } planPIndexesNext := cbgt.CopyPlanPIndexes(planPIndexesPrev, version) for planPIndexName, planPIndex := range planPIndexesNext.PlanPIndexes { for node, planPIndexNode := range planPIndex.Nodes { if !mapNodesFailover[node] { continue } if planPIndexNode.Priority <= 0 { // Failover'ed node used to be a primary for this // pindex, so find a replica to promote. promoted := "" PROMOTE_REPLICA: for nodePro, ppnPro := range planPIndex.Nodes { if mapNodesFailover[nodePro] { continue } if ppnPro.Priority >= 1 { ppnPro.Priority = 0 planPIndex.Nodes[nodePro] = ppnPro promoted = nodePro break PROMOTE_REPLICA } } // If we didn't find a replica to promote, and we're // configured with the option to // "failoverAssignAllPrimaries-IndexName" or // "failoverAssignAllPrimaries" (default true), then // assign the primary from the calculated plan. if promoted == "" && ParseOptionsBool(options, "failoverAssignAllPrimaries", planPIndex.IndexName, true) { planPIndexCalc, exists := planPIndexesCalc.PlanPIndexes[planPIndexName] if exists && planPIndexCalc != nil { ASSIGN_PRIMARY: for nodeCalc, ppnCalc := range planPIndexCalc.Nodes { if ppnCalc.Priority <= 0 && !mapNodesFailover[nodeCalc] { planPIndex.Nodes[nodeCalc] = ppnCalc promoted = nodeCalc break ASSIGN_PRIMARY } } } } } delete(planPIndex.Nodes, node) } } // TODO: Missing under-replication constraint warnings. if cbgt.SamePlanPIndexes(planPIndexesNext, planPIndexesPrev) { return false, nil } _, err = cbgt.CfgSetPlanPIndexes(cfg, planPIndexesNext, cas) if err != nil { return false, fmt.Errorf("planner: failover could not save plan,"+ " perhaps a concurrent planner won, cas: %d, err: %v", cas, err) } return true, nil }
// Failover promotes replicas to primary for the remaining nodes. func Failover(cfg cbgt.Cfg, version string, server string, nodesFailover []string) (bool, error) { mapNodesFailover := cbgt.StringsToMap(nodesFailover) uuid := "" indexDefs, nodeDefs, planPIndexesPrev, cas, err := cbgt.PlannerGetPlan(cfg, version, uuid) if err != nil { return false, err } planPIndexesCalc, err := cbgt.CalcPlan("failover", indexDefs, nodeDefs, planPIndexesPrev, version, server) if err != nil { return false, fmt.Errorf("planner: failover CalcPlan, err: %v", err) } planPIndexesNext := cbgt.CopyPlanPIndexes(planPIndexesPrev, version) for planPIndexName, planPIndex := range planPIndexesNext.PlanPIndexes { for node, planPIndexNode := range planPIndex.Nodes { if !mapNodesFailover[node] { continue } if planPIndexNode.Priority <= 0 { // Failover'ed node used to be a primary for this // pindex, so find a replica to promote. promoted := "" PROMOTE_REPLICA: for nodePro, ppnPro := range planPIndex.Nodes { if mapNodesFailover[nodePro] { continue } if ppnPro.Priority >= 1 { ppnPro.Priority = 0 planPIndex.Nodes[nodePro] = ppnPro promoted = nodePro break PROMOTE_REPLICA } } if promoted == "" { // Didn't find a replica to promote, so consult the // calculated plan for the primary assignment. planPIndexCalc, exists := planPIndexesCalc.PlanPIndexes[planPIndexName] if exists && planPIndexCalc != nil { PROMOTE_CALC: for nodeCalc, ppnCalc := range planPIndexCalc.Nodes { if ppnCalc.Priority <= 0 && !mapNodesFailover[nodeCalc] { planPIndex.Nodes[nodeCalc] = ppnCalc promoted = nodeCalc break PROMOTE_CALC } } } } } delete(planPIndex.Nodes, node) } } // TODO: Missing under-replication constraint warnings. if cbgt.SamePlanPIndexes(planPIndexesNext, planPIndexesPrev) { return false, nil } _, err = cbgt.CfgSetPlanPIndexes(cfg, planPIndexesNext, cas) if err != nil { return false, fmt.Errorf("planner: failover could not save plan,"+ " perhaps a concurrent planner won, cas: %d, err: %v", cas, err) } return true, nil }