// calcBegEndMaps calculates the before and after maps for an index. func (r *Rebalancer) calcBegEndMaps(indexDef *cbgt.IndexDef) ( partitionModel blance.PartitionModel, begMap blance.PartitionMap, endMap blance.PartitionMap, err error) { r.m.Lock() defer r.m.Unlock() // The endPlanPIndexesForIndex is a working data structure that's // mutated as calcBegEndMaps progresses. endPlanPIndexesForIndex, err := cbgt.SplitIndexDefIntoPlanPIndexes( indexDef, r.server, r.endPlanPIndexes) if err != nil { r.Logf(" calcBegEndMaps: indexDef.Name: %s,"+ " could not SplitIndexDefIntoPlanPIndexes,"+ " server: %s, err: %v", indexDef.Name, r.server, err) return partitionModel, begMap, endMap, err } // Invoke blance to assign the endPlanPIndexesForIndex to nodes. warnings := cbgt.BlancePlanPIndexes("", indexDef, endPlanPIndexesForIndex, r.begPlanPIndexes, r.nodesAll, r.nodesToAdd, r.nodesToRemove, r.nodeWeights, r.nodeHierarchy) r.endPlanPIndexes.Warnings[indexDef.Name] = warnings for _, warning := range warnings { r.Logf(" calcBegEndMaps: indexDef.Name: %s,"+ " BlancePlanPIndexes warning: %q", indexDef.Name, warning) } j, _ := json.Marshal(r.endPlanPIndexes) r.Logf(" calcBegEndMaps: indexDef.Name: %s,"+ " endPlanPIndexes: %s", indexDef.Name, j) partitionModel, _ = cbgt.BlancePartitionModel(indexDef) begMap = cbgt.BlanceMap(endPlanPIndexesForIndex, r.begPlanPIndexes) endMap = cbgt.BlanceMap(endPlanPIndexesForIndex, r.endPlanPIndexes) return partitionModel, begMap, endMap, nil }
// When the index definitions have changed, our approach is to run the // planner, but only for brand new indexes that don't have any // pindexes yet. func (ctl *Ctl) IndexDefsChanged() (err error) { plannerFilterNewIndexesOnly := func(indexDef *cbgt.IndexDef, planPIndexesPrev, planPIndexes *cbgt.PlanPIndexes) bool { copyPrevPlan := func() { // Copy over the previous plan, if any, for the index. if planPIndexesPrev != nil && planPIndexes != nil { for n, p := range planPIndexesPrev.PlanPIndexes { if p.IndexName == indexDef.Name && p.IndexUUID == indexDef.UUID { planPIndexes.PlanPIndexes[n] = p // Copy over previous warnings, if any. if planPIndexes.Warnings == nil { planPIndexes.Warnings = map[string][]string{} } if planPIndexesPrev.Warnings != nil { prev := planPIndexesPrev.Warnings[indexDef.Name] if prev != nil { planPIndexes.Warnings[indexDef.Name] = prev } } } } } } // Split each indexDef into 1 or more PlanPIndexes. planPIndexesForIndex, err := cbgt.SplitIndexDefIntoPlanPIndexes( indexDef, ctl.server, ctl.optionsMgr, nil) if err != nil { copyPrevPlan() return false } for pindexName := range planPIndexesForIndex { if planPIndexesPrev.PlanPIndexes[pindexName] != nil { copyPrevPlan() return false } } return true } go func() { steps := map[string]bool{"planner": true} var nodesToRemove []string cmd.PlannerSteps(steps, ctl.cfg, cbgt.VERSION, ctl.server, ctl.optionsMgr, nodesToRemove, ctl.optionsCtl.DryRun, plannerFilterNewIndexesOnly) planPIndexes, _, err := cbgt.PlannerGetPlanPIndexes(ctl.cfg, cbgt.VERSION) if err == nil && planPIndexes != nil { ctl.m.Lock() ctl.incRevNumLOCKED() ctl.prevWarnings = planPIndexes.Warnings ctl.m.Unlock() } }() return nil }