diff --git a/plugin/move_leader/Makefile b/plugin/move_leader/Makefile deleted file mode 100644 index 63be8680e00..00000000000 --- a/plugin/move_leader/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -moveLeaderPlugin.so: *.go - GO111MODULE=on GO_ENABLED=1 go build -race -gcflags '' -ldflags '-X "github.com/pingcap/pd/server.PDReleaseVersion=v4.0.0-alpha-54-ge678a1f-dirty" -X "github.com/pingcap/pd/server.PDBuildTS=2019-09-19 06:42:25" -X "github.com/pingcap/pd/server.PDGitHash=e678a1f5c022fed729fb79397fe02b6c9f54ff4a" -X "github.com/pingcap/pd/server.PDGitBranch=master"' -buildmode=plugin -o moveLeaderPlugin.so *.go - -.PHONY : clean - -clean: - rm moveLeaderPlugin.so diff --git a/plugin/move_leader/config_test.go b/plugin/move_leader/config_test.go deleted file mode 100644 index 82b2b94df93..00000000000 --- a/plugin/move_leader/config_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package main - -import ( - "bufio" - . "github.com/pingcap/check" - "github.com/pingcap/pd/pkg/mock/mockcluster" - _ "github.com/pingcap/pd/pkg/mock/mockcluster" - "github.com/pingcap/pd/pkg/mock/mockhbstream" - "github.com/pingcap/pd/pkg/mock/mockoption" - "github.com/pingcap/pd/server/schedule" - "os" - "path/filepath" - "strconv" - "strings" - "time" -) - -var _ = Suite(&testUserConfigSuite{}) - -type testUserConfigSuite struct { -} - -// Test config parse -// Compare the results of the parse with the results of reading the file directly -func (s *testUserConfigSuite) TestReadUserConfig(c *C) { - filePath, err := filepath.Abs("../conf/test_config.toml") - c.Assert(err, IsNil) - uc := NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, true) - schedule.PluginsMapLock.RLock() - defer schedule.PluginsMapLock.RUnlock() - f, err := os.Open(filePath) - c.Assert(err, IsNil) - defer f.Close() - br := bufio.NewReader(f) - var line string - names := []string{"Leader-0", "Leader-1", "Region-0", "Region-1"} - for _, name := range names { - pluginInfo := schedule.PluginsMap[name] - line, err = br.ReadString('\n') - if strings.Contains(line, "[[") == false { - line, err = br.ReadString('\n') - } - line, err = br.ReadString('\n') - c.Assert(strings.Contains(line, strconv.FormatBool(pluginInfo.Persist)), Equals, true) - line, err = br.ReadString('\n') - c.Assert(strings.Contains(line, pluginInfo.GetKeyStart()), Equals, true) - line, err = br.ReadString('\n') - c.Assert(strings.Contains(line, pluginInfo.GetKeyEnd()), Equals, true) - line, err = br.ReadString('"') - line, err = br.ReadString('+') - line = strings.Replace(line, "+", "", -1) - line = strings.Replace(line, "T", " ", -1) - t, _ := time.ParseInLocation("2006-01-02 15:04:05", line, time.Local) - line, err = br.ReadString('\n') - c.Assert(pluginInfo.Interval.Begin.Format("2006-01-02 15:04:05"), Equals, t.Format("2006-01-02 15:04:05")) - line, err = br.ReadString('"') - line, err = br.ReadString('+') - line = strings.Replace(line, "+", "", -1) - line = strings.Replace(line, "T", " ", -1) - t, _ = time.ParseInLocation("2006-01-02 15:04:05", line, time.Local) - line, err = br.ReadString('\n') - c.Assert(pluginInfo.Interval.End.Format("2006-01-02 15:04:05"), Equals, t.Format("2006-01-02 15:04:05")) - - for _, store := range pluginInfo.Stores { - line, err = br.ReadString('\n') - for _, label := range store.StoreLabel { - line, err = br.ReadString('\n') - line, err = br.ReadString('\n') - c.Assert(strings.Contains(line, label.Key), Equals, true) - line, err = br.ReadString('\n') - c.Assert(strings.Contains(line, label.Value), Equals, true) - } - } - } -} - -// test_config.toml contains 4 rules -// ProduceScheduler() will finally produce 4 schedulers -func (s *testUserConfigSuite) TestProduceScheduler(c *C) { - opt := mockoption.NewScheduleOptions() - cluster := mockcluster.NewCluster(opt) - htStream := mockhbstream.NewHeartbeatStream() - opc := schedule.NewOperatorController(cluster, htStream) - filePath, err := filepath.Abs("../conf/test_config.toml") - c.Assert(err, IsNil) - uc := NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, true) - - cluster.PutStoreWithLabels(1, "zone", "z1", "rack", "r1", "host", "h1") - cluster.PutStoreWithLabels(2, "zone", "z2", "rack", "r2", "host", "h2") - cluster.PutStoreWithLabels(3, "zone", "z3", "rack", "r3", "host", "h3") - cluster.PutStoreWithLabels(4, "zone", "z4", "rack", "r4", "host", "h4") - cluster.PutStoreWithLabels(5, "zone", "z5", "rack", "r5", "host", "h5") - schedulers := ProduceScheduler(uc, opc, cluster) - c.Assert(schedulers, NotNil) - c.Assert(len(schedulers), Equals, 4) -} - -func (s *testUserConfigSuite) TestGetStoreId(c *C) { - opt := mockoption.NewScheduleOptions() - cluster := mockcluster.NewCluster(opt) - cluster.PutStoreWithLabels(1, "zone", "z1", "rack", "r1", "host", "h1") - cluster.PutStoreWithLabels(2, "zone", "z2", "rack", "r2", "host", "h2") - cluster.PutStoreWithLabels(3, "zone", "z3", "rack", "r3", "host", "h3") - cluster.PutStoreWithLabels(4, "zone", "z4", "rack", "r4", "host", "h4") - cluster.PutStoreWithLabels(5, "zone", "z5", "rack", "r5", "host", "h5") - - filePath, err := filepath.Abs("../conf/test_config.toml") - c.Assert(err, IsNil) - uc := NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, true) - schedule.PluginsMapLock.RLock() - defer schedule.PluginsMapLock.RUnlock() - for name, stores := range uc.GetStoreId(cluster) { - if name == "Leader-0" { - c.Assert(stores[0], Equals, uint64(3)) - }else if name == "Leader-1" { - c.Assert(stores[0], Equals, uint64(1)) - c.Assert(stores[1], Equals, uint64(5)) - }else if name == "Region-0" { - c.Assert(stores[0], Equals, uint64(1)) - c.Assert(stores[1], Equals, uint64(2)) - c.Assert(stores[2], Equals, uint64(3)) - }else if name == "Region-1" { - c.Assert(stores[0], Equals, uint64(4)) - c.Assert(stores[1], Equals, uint64(5)) - } - } -} - -func (s *testUserConfigSuite) TestGetInterval(c *C) { - filePath, err := filepath.Abs("../conf/test_config.toml") - c.Assert(err, IsNil) - uc := NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, true) - schedule.PluginsMapLock.RLock() - defer schedule.PluginsMapLock.RUnlock() - for name, interval := range uc.GetInterval() { - if name == "Leader-0" { - begin, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-05 14:55:00", time.Local) - c.Assert(interval.GetBegin().Format("2006-01-02 15:04:05"), Equals, begin.Format("2006-01-02 15:04:05")) - end, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-30 10:30:00", time.Local) - c.Assert(interval.GetEnd().Format("2006-01-02 15:04:05"), Equals, end.Format("2006-01-02 15:04:05")) - }else if name == "Leader-1" { - begin, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-05 07:30:00", time.Local) - c.Assert(interval.GetBegin().Format("2006-01-02 15:04:05"), Equals, begin.Format("2006-01-02 15:04:05")) - end, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-30 10:30:00", time.Local) - c.Assert(interval.GetEnd().Format("2006-01-02 15:04:05"), Equals, end.Format("2006-01-02 15:04:05")) - }else if name == "Region-0" { - begin, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-05 07:30:00", time.Local) - c.Assert(interval.GetBegin().Format("2006-01-02 15:04:05"), Equals, begin.Format("2006-01-02 15:04:05")) - end, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-30 10:30:00", time.Local) - c.Assert(interval.GetEnd().Format("2006-01-02 15:04:05"), Equals, end.Format("2006-01-02 15:04:05")) - }else if name == "Region-1" { - begin, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-05 07:30:00", time.Local) - c.Assert(interval.GetBegin().Format("2006-01-02 15:04:05"), Equals, begin.Format("2006-01-02 15:04:05")) - end, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-30 10:30:00", time.Local) - c.Assert(interval.GetEnd().Format("2006-01-02 15:04:05"), Equals, end.Format("2006-01-02 15:04:05")) - } - } -} - -// Test irreconcilable conflict -func (s *testUserConfigSuite) TestConflict(c *C) { - opt := mockoption.NewScheduleOptions() - cluster := mockcluster.NewCluster(opt) - htStream := mockhbstream.NewHeartbeatStream() - opc := schedule.NewOperatorController(cluster, htStream) - filePath, err := filepath.Abs("../conf/test_conflict.toml") - c.Assert(err, IsNil) - uc := NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, false) - c.Assert(uc.IfConflict(3), Equals, true) - c.Assert(uc.IfConflict(2), Equals, true) - schedulers := ProduceScheduler(uc, opc, cluster) - c.Assert(schedulers, NotNil) - c.Assert(len(schedulers), Equals, 0) -} - -func (s *testUserConfigSuite) TestIfOverlap(c *C) { - c.Assert(len(IfOverlap([]uint64{1, 2, 3}, []uint64{2, 3, 4})), Equals, 2) - c.Assert(len(IfOverlap([]uint64{1, 2, 3}, []uint64{4, 5, 6})), Equals, 0) -} diff --git a/plugin/move_leader/filters.go b/plugin/move_leader/filters.go deleted file mode 100644 index 4cccea4c9a7..00000000000 --- a/plugin/move_leader/filters.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "github.com/pingcap/pd/server/core" - "github.com/pingcap/pd/server/schedule" - "github.com/pingcap/pd/server/schedule/opt" - "time" -) - -type violentFilter struct { -} - -func NewViolentFilter() schedule.RegionFilter { - return &violentFilter{} -} - -func (f *violentFilter) Type() string { - return "violent-filter" -} - -func (f *violentFilter) FilterSource(opt opt.Options, region *core.RegionInfo, interval *schedule.TimeInterval, regionIDs []uint64) bool { - if interval != nil { - currentTime := time.Now() - if currentTime.After(interval.End) || interval.Begin.After(currentTime) { - return false - } - } - return f.isExists(region.GetID(), regionIDs) -} - -func (f *violentFilter) FilterTarget(opt opt.Options, region *core.RegionInfo, interval *schedule.TimeInterval, regionIDs []uint64) bool { - if interval != nil { - currentTime := time.Now() - if currentTime.After(interval.End) || interval.Begin.After(currentTime) { - return false - } - } - return f.isExists(region.GetID(), regionIDs) -} - -func (f *violentFilter) isExists(regionID uint64, regionIDs []uint64) bool { - for _, id := range regionIDs { - if id == regionID { - return true - } - } - return false -} diff --git a/plugin/move_leader/move_leader.go b/plugin/move_leader/move_leader.go deleted file mode 100644 index be4f2400cf7..00000000000 --- a/plugin/move_leader/move_leader.go +++ /dev/null @@ -1,169 +0,0 @@ -package main - -import ( - "time" - - "github.com/pingcap/log" - "github.com/pingcap/pd/server/core" - "github.com/pingcap/pd/server/schedule" - "github.com/pingcap/pd/server/schedule/operator" - "github.com/pingcap/pd/server/schedule/filter" - "go.uber.org/zap" -) - -type moveLeaderUserScheduler struct { - *userBaseScheduler - name string - opController *schedule.OperatorController - storeIDs []uint64 - keyStart string - keyEnd string - storeSeq int - timeInterval *schedule.TimeInterval -} - -// Only use for register scheduler -// newMoveLeaderUserScheduler() will be called manually -func init() { - schedule.RegisterScheduler("move-leader-user", func(opController *schedule.OperatorController, args []string) (schedule.Scheduler, error) { - return newMoveLeaderUserScheduler(opController, "", "", "", []uint64{}, nil), nil - }) -} - -func newMoveLeaderUserScheduler(opController *schedule.OperatorController, name, keyStart, keyEnd string, storeIDs []uint64, interval *schedule.TimeInterval) schedule.Scheduler { - log.Info("", zap.String("New", name), zap.Strings("key range", []string{keyStart, keyEnd})) - base := newUserBaseScheduler(opController) - return &moveLeaderUserScheduler{ - userBaseScheduler: base, - name: name, - storeIDs: storeIDs, - keyStart: keyStart, - keyEnd: keyEnd, - storeSeq: 0, - timeInterval: interval, - opController: opController, - } -} - -func (l *moveLeaderUserScheduler) GetName() string { - return l.name -} - -func (l *moveLeaderUserScheduler) GetType() string { - return "move-leader-user" -} - -func (l *moveLeaderUserScheduler) IsScheduleAllowed(cluster schedule.Cluster) bool { - return l.opController.OperatorCount(operator.OpLeader) < cluster.GetLeaderScheduleLimit() -} - -func (l *moveLeaderUserScheduler) Schedule(cluster schedule.Cluster) []*operator.Operator { - schedule.PluginsInfoMapLock.RLock() - defer schedule.PluginsInfoMapLock.RUnlock() - // Determine if there is a time limit - if l.timeInterval != nil { - currentTime := time.Now() - if currentTime.After(l.timeInterval.GetEnd()) || l.timeInterval.GetBegin().After(currentTime) { - return nil - } - } - // When region ids change, re-output scheduler's regions and stores - regionIDs := schedule.GetRegionIDs(cluster, l.keyStart, l.keyEnd) - //log.Info("", zap.String("Schedule()", l.GetName()), zap.Uint64s("Regions", regionIDs)) - //log.Info("", zap.String("Schedule()", l.GetName()), zap.Uint64s("Stores", l.storeIDs)) - - if len(l.storeIDs) == 0 { - return nil - } - - for _, regionID := range regionIDs { - region := cluster.GetRegion(regionID) - if region == nil { - log.Info("region not exist", zap.Uint64("region-id", regionID)) - continue - } - sourceID := region.GetLeader().GetStoreId() - source := cluster.GetStore(sourceID) - // If leader is in target stores, - // it means user's rules has been met, - // then do nothing - if !l.isExists(sourceID, l.storeIDs) { - // Let "seq" store be the target first - targetID := l.storeIDs[l.storeSeq] - // seq increase - if l.storeSeq < len(l.storeIDs)-1 { - l.storeSeq++ - } else { - l.storeSeq = 0 - } - target := cluster.GetStore(targetID) - if _, ok := region.GetStoreIds()[targetID]; ok { - // target store has region peer, so do "transfer leader" - filters := []filter.Filter{ - filter.StoreStateFilter{TransferLeader: true}, - } - if filter.Source(cluster, source, filters) { - log.Info("filter source", - zap.String("scheduler", l.GetName()), - zap.Uint64("region-id", regionID), - zap.Uint64("store-id", sourceID)) - continue - } - if filter.Target(cluster, target, filters) { - log.Info("filter target", - zap.String("scheduler", l.GetName()), - zap.Uint64("region-id", regionID), - zap.Uint64("store-id", targetID)) - continue - } - op := operator.CreateTransferLeaderOperator("move-leader-user", region, sourceID, targetID, operator.OpLeader) - op.SetPriorityLevel(core.HighPriority) - return []*operator.Operator{op} - } else { - // target store doesn't have region peer, so do "move leader" - filters := []filter.Filter{ - filter.StoreStateFilter{MoveRegion: true}, - } - if filter.Source(cluster, source, filters) { - log.Info("filter source", - zap.String("scheduler", l.GetName()), - zap.Uint64("region-id", regionID), - zap.Uint64("store-id", sourceID)) - continue - } - if filter.Target(cluster, target, filters) { - log.Info("filter target", - zap.String("scheduler", l.GetName()), - zap.Uint64("region-id", regionID), - zap.Uint64("store-id", targetID)) - continue - } - destPeer, err := cluster.AllocPeer(targetID) - if err != nil { - log.Error("failed to allocate peer", zap.Error(err)) - continue - } - op, err := operator.CreateMoveLeaderOperator("move-leader-user", cluster, region, operator.OpAdmin, sourceID, targetID, destPeer.GetId()) - if err != nil { - log.Error("CreateMoveLeaderOperator Err", - zap.String("scheduler", l.GetName()), - zap.Error(err)) - continue - } - op.SetPriorityLevel(core.HighPriority) - return []*operator.Operator{op} - } - } - } - return nil -} - -// isExists(ID , IDs) determine if the ID is in IDs -func (l *moveLeaderUserScheduler) isExists(ID uint64, IDs []uint64) bool { - for _, id := range IDs { - if id == ID { - return true - } - } - return false -} diff --git a/plugin/move_leader/move_test.go b/plugin/move_leader/move_test.go deleted file mode 100644 index 8694740d746..00000000000 --- a/plugin/move_leader/move_test.go +++ /dev/null @@ -1,242 +0,0 @@ -package main - -import ( - "encoding/hex" - . "github.com/pingcap/check" - _ "github.com/pingcap/log" - "github.com/pingcap/pd/pkg/mock/mockcluster" - "github.com/pingcap/pd/pkg/mock/mockoption" - "github.com/pingcap/pd/pkg/testutil" - "github.com/pingcap/pd/server/schedule" - _ "go.uber.org/zap" - "path/filepath" - "strings" - "testing" - "time" -) - -func TestPluginCode(t *testing.T) { - TestingT(t) -} - -type testPluginCodeSuite struct { - tc *mockcluster.Cluster - oc *schedule.OperatorController -} - -var _ = Suite(&testPluginCodeSuite{}) - -func (s *testPluginCodeSuite) SetUpTest(c *C) { - opt := mockoption.NewScheduleOptions() - s.tc = mockcluster.NewCluster(opt) - s.oc = schedule.NewOperatorController(nil, nil) - //Stores: 1 2 3 4 5 - //"zone" z1 z2 z3 z4 z5 - //"rock" r1 r2 r3 r4 r5 - //"host" h1 h2 h3 h4 h5 - //Region1: L F F - - - //Region2: F L F - - - //Region3: - F - L F - //Region4: - F L F - - //Region5: F - - F L - //Region6: - - F F L - //Region7: L F - - F - //Region8: F - F L - - //Region9: - L F - F - //Region10: - F L F - - s.tc.PutStoreWithLabels(1, "zone", "z1", "rack", "r1", "host", "h1") - s.tc.SetStoreUp(1) - s.tc.PutStoreWithLabels(2, "zone", "z2", "rack", "r2", "host", "h2") - s.tc.SetStoreUp(2) - s.tc.PutStoreWithLabels(3, "zone", "z3", "rack", "r3", "host", "h3") - s.tc.SetStoreUp(3) - s.tc.PutStoreWithLabels(4, "zone", "z4", "rack", "r4", "host", "h4") - s.tc.SetStoreUp(4) - s.tc.PutStoreWithLabels(5, "zone", "z5", "rack", "r5", "host", "h5") - s.tc.SetStoreUp(5) - s.tc.AddLeaderRegionWithRange(1, - "", - DecodeToString("757365727461626C653A7573657231773937383833313437333137333731323135"), 1, 2, 3) - s.tc.AddLeaderRegionWithRange(2, - DecodeToString("757365727461626C653A7573657231773937383833313437333137333731323135"), - DecodeToString("757365727461626C653A7573657232643637353232383738383832303830353737"), 2, 1, 3) - s.tc.AddLeaderRegionWithRange(3, - DecodeToString("757365727461626C653A7573657232643637353232383738383832303830353737"), - DecodeToString("757365727461626C653A7573657233943637353232383738383832303830353737"), 4, 2, 5) - s.tc.AddLeaderRegionWithRange(4, - DecodeToString("757365727461626C653A7573657233943637353232383738383832303830353737"), - DecodeToString("757365727461626C653A7573657234443637353232383738383832303830353737"), 3, 2, 4) - s.tc.AddLeaderRegionWithRange(5, - DecodeToString("757365727461626C653A7573657234443637353232383738383832303830353737"), - DecodeToString("757365727461626C653A7573657235743637353232383738383832303830353737"), 5, 1, 4) - s.tc.AddLeaderRegionWithRange(6, - DecodeToString("757365727461626C653A7573657235743637353232383738383832303830353737"), - DecodeToString("757365727461626C653A7573657236273036373639353831393732343031333937"), 5, 3, 4) - s.tc.AddLeaderRegionWithRange(7, - DecodeToString("757365727461626C653A7573657236273036373639353831393732343031333937"), - DecodeToString("757365727461626C653A7573657236973036373639353831393732343031333937"), 1, 2, 5) - s.tc.AddLeaderRegionWithRange(8, - DecodeToString("757365727461626C653A7573657236973036373639353831393732343031333937"), - DecodeToString("757365727461626C653A7573657238373036373639353831393732343031333937"), 4, 1, 3) - s.tc.AddLeaderRegionWithRange(9, - DecodeToString("757365727461626C653A7573657238373036373639353831393732343031333937"), - DecodeToString("757365727461626C653A7573657239973036373639353831393732343031333937"), 2, 3, 5) - s.tc.AddLeaderRegionWithRange(10, - DecodeToString("757365727461626C653A7573657239973036373639353831393732343031333937"), - "", 3, 2, 4) - -} - -func (s *testPluginCodeSuite) TestMoveScheduler(c *C) { - filePath, err := filepath.Abs("../conf/test_config.toml") - c.Assert(err, IsNil) - uc := NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, true) - c.Assert(uc, NotNil) - - - schedule.PluginsMapLock.RLock() - names := []string{} - for name, _ := range schedule.PluginsMap { - names = append(names, name) - } - schedule.PluginsMapLock.RUnlock() - - for _, name := range names { - ss := strings.Split(name, "-") - if ss[0] == "Leader" { - schedule.PluginsMapLock.Lock() - schedule.PluginsMap[name].UpdateStoreIDs(s.tc) - lb := newMoveLeaderUserScheduler(s.oc, "move-leader-user-scheduler-"+ss[1], - schedule.PluginsMap[name].GetKeyStart(), schedule.PluginsMap[name].GetKeyEnd(), - schedule.PluginsMap[name].GetStoreIDs(), schedule.PluginsMap[name].GetInterval()) - schedule.PluginsMapLock.Unlock() - c.Assert(lb, NotNil) - c.Assert(lb.GetType(), Equals, "move-leader-user") - c.Assert(lb.IsScheduleAllowed(s.tc), Equals, true) - op := lb.Schedule(s.tc)[0] - c.Assert(op, NotNil) - if ss[1] == "0" { - //transferLeader - //region2 leader form store 2 to 3 - c.Assert(lb.GetName(), Equals, "move-leader-user-scheduler-0") - testutil.CheckTransferLeader(c, op, schedule.OpLeader, 2, 3) - c.Assert(op.RegionID(), Equals, uint64(2)) - } else if ss[1] == "1" { - //moveLeader - //region4 leader from store 3 to 1 - //addPeer 2 steps; removePeer 2 steps; transferLeader 1 step - c.Assert(lb.GetName(), Equals, "move-leader-user-scheduler-1") - c.Assert(op.Len(), Equals, 5) - c.Assert(op.Kind()&schedule.OpLeader, Equals, schedule.OpLeader) - c.Assert(op.RegionID(), Equals, uint64(4)) - } - } - if ss[0] == "Region" { - schedule.PluginsMapLock.Lock() - schedule.PluginsMap[name].UpdateStoreIDs(s.tc) - lb := newMoveRegionUserScheduler(s.oc, "move-region-user-scheduler-"+ss[1], - schedule.PluginsMap[name].GetKeyStart(), schedule.PluginsMap[name].GetKeyEnd(), - schedule.PluginsMap[name].GetStoreIDs(), schedule.PluginsMap[name].GetInterval()) - schedule.PluginsMapLock.Unlock() - c.Assert(lb, NotNil) - c.Assert(lb.GetType(), Equals, "move-region-user") - c.Assert(lb.IsScheduleAllowed(s.tc), Equals, true) - op := lb.Schedule(s.tc)[0] - c.Assert(op, NotNil) - if ss[1] == "0" { - //move region6 to store 1 2 3 - //2 addPeer 4 steps; transferLeader 1 step;2 removePeer 2 steps - c.Assert(lb.GetName(), Equals, "move-region-user-scheduler-0") - c.Assert(op.Len(), Equals, 7) - c.Assert(op.Kind()&schedule.OpRegion, Equals, schedule.OpRegion) - c.Assert(op.RegionID(), Equals, uint64(6)) - } else if ss[1] == "1" { - //move region8 to store 4 5 - //addPeer 2 steps; removePeer 1 step - c.Assert(lb.GetName(), Equals, "move-region-user-scheduler-1") - c.Assert(op.Len(), Equals, 3) - c.Assert(op.Kind()&schedule.OpRegion, Equals, schedule.OpRegion) - c.Assert(op.RegionID(), Equals, uint64(8)) - } - } - } - // test move-leader and move-region schedulers adjustable conflict - filePath, err = filepath.Abs("../conf/test_conflict2.toml") - c.Assert(err, IsNil) - uc = NewUserConfig() - c.Assert(uc.LoadConfig(filePath, 3), Equals, true) - c.Assert(uc, NotNil) - schedule.PluginsMapLock.Lock() - name := "Leader-1" - schedule.PluginsMap[name].UpdateStoreIDs(s.tc) - lb := newMoveLeaderUserScheduler(s.oc, "move-leader-user-scheduler-"+"2", - schedule.PluginsMap[name].GetKeyStart(), schedule.PluginsMap[name].GetKeyEnd(), - schedule.PluginsMap[name].GetStoreIDs(), schedule.PluginsMap[name].GetInterval()) - schedule.PluginsMapLock.Unlock() - c.Assert(lb, NotNil) - c.Assert(lb.GetType(), Equals, "move-leader-user") - c.Assert(lb.IsScheduleAllowed(s.tc), Equals, true) - ops := lb.Schedule(s.tc) - c.Assert(ops, NotNil) -} - -func DecodeToString(source string) string { - key, _ := hex.DecodeString(source) - return string(key) -} - -func (s *testPluginCodeSuite) TestFilter(c *C) { - s.tc.AddLeaderStore(11, 3) - s.tc.AddLeaderStore(12, 3) - s.tc.AddLeaderStore(13, 3) - s.tc.AddLeaderRegion(21, 11, 12, 13) - s.tc.AddLeaderRegion(22, 12, 11, 13) - startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-01-02 15:04:05", time.Local) - endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-10-02 15:04:05", time.Local) - interval := schedule.TimeInterval{ - Begin: startTime, - End: endTime, - } - filter := NewViolentFilter() - c.Assert(filter, NotNil) - c.Assert(filter.Type(), Equals, "violent-filter") - c.Assert(filter.FilterSource(s.tc, s.tc.GetRegion(21), &interval, []uint64{21, 22, 23}), Equals, true) - c.Assert(filter.FilterSource(s.tc, s.tc.GetRegion(21), &interval, []uint64{20, 22, 23}), Equals, false) - c.Assert(filter.FilterTarget(s.tc, s.tc.GetRegion(22), &interval, []uint64{21, 22, 23}), Equals, true) - c.Assert(filter.FilterTarget(s.tc, s.tc.GetRegion(22), &interval, []uint64{1, 2, 3}), Equals, false) -} - -func (s *testPluginCodeSuite) TestBaseScheduler(c *C) { - lb := newUserBaseScheduler(s.oc) - c.Assert(lb, NotNil) - c.Assert(lb.GetMinInterval(), Equals, MinScheduleInterval) - interval := time.Duration(1000) - c.Assert(lb.GetNextInterval(interval), Equals, time.Duration(1300)) -} - -//test structure.go -//func GetRegionIDs() -func (s *testPluginCodeSuite) TestGetRegionIDs(c *C) { - regionIDs := schedule.GetRegionIDs(s.tc,"757365727461626C653A7573657231773937383833313437333137333731323135", - "757365727461626C653A7573657234443637353232383738383832303830353737") - c.Assert(len(regionIDs), Equals, 3) - c.Assert(regionIDs[0], Equals, uint64(2)) - c.Assert(regionIDs[1], Equals, uint64(3)) - c.Assert(regionIDs[2], Equals, uint64(4)) -} - -//test structure.go -//func GetStoreByLabel() -func (s *testPluginCodeSuite) TestGetStoreByLabel(c *C) { - label1 := schedule.Label{Key: "zone", Value: "z1"} - label2 := schedule.Label{Key: "rack", Value: "r1"} - label3 := schedule.Label{Key: "host", Value: "h1"} - c.Assert(schedule.GetStoreByLabel(s.tc, []schedule.Label{label1,label2,label3}), NotNil) -} - -//func (s *testPluginCodeSuite) TestGetFunction(c *C) { -// f, err := schedule.GetFunction("../plugin/userConfigPlugin.so", "NewUserConfig") -// c.Assert(err, IsNil) -// c.Assert(f, NotNil) -//} \ No newline at end of file diff --git a/plugin/move_leader/read_user_config.go b/plugin/move_leader/read_user_config.go deleted file mode 100644 index b93a7f14cbe..00000000000 --- a/plugin/move_leader/read_user_config.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "github.com/pingcap/pd/server/schedule" - "strings" -) - -func ProduceScheduler(cfg schedule.Config, opController *schedule.OperatorController, cluster schedule.Cluster) []schedule.Scheduler { - storeMap := cfg.GetStoreId(cluster) - intervalMaps := cfg.GetInterval() - schedules := []schedule.Scheduler{} - - schedule.PluginsInfoMapLock.Lock() - defer schedule.PluginsInfoMapLock.Unlock() - // produce schedulers - for str, storeIDs := range storeMap { - schedule.PluginsInfoMap[str].UpdateStoreIDs(cluster) - s := strings.Split(str, "-") - name := "move-leader-use-scheduler-" + s[1] - schedules = append(schedules, - newMoveLeaderUserScheduler(opController, name, - schedule.PluginsInfoMap[str].GetKeyStart(), schedule.PluginsInfoMap[str].GetKeyEnd(), storeIDs, intervalMaps[str])) - } - - return schedules -} diff --git a/plugin/move_leader/signal.sh b/plugin/move_leader/signal.sh deleted file mode 100644 index 59d72878e1e..00000000000 --- a/plugin/move_leader/signal.sh +++ /dev/null @@ -1,2 +0,0 @@ -pid=`ps -ef|grep -E pd-server | grep -v "grep" | awk '{print $2}'` -kill -SIGUSR1 $pid diff --git a/plugin/move_leader/user_base_scheduler.go b/plugin/move_leader/user_base_scheduler.go deleted file mode 100644 index 8a7ef1abf1c..00000000000 --- a/plugin/move_leader/user_base_scheduler.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "github.com/pingcap/pd/server/schedule" - "time" -) - -type userBaseScheduler struct { - opController *schedule.OperatorController -} - -// options for interval of schedulers -const ( - MaxScheduleInterval = time.Second * 5 - MinScheduleInterval = time.Millisecond * 10 - - ScheduleIntervalFactor = 1.3 -) - -func newUserBaseScheduler(opController *schedule.OperatorController) *userBaseScheduler { - return &userBaseScheduler{opController: opController} -} - -func (s *userBaseScheduler) Prepare(cluster schedule.Cluster) error { return nil } - -func (s *userBaseScheduler) Cleanup(cluster schedule.Cluster) {} - -func (s *userBaseScheduler) GetMinInterval() time.Duration { - return MinScheduleInterval -} - -func (s *userBaseScheduler) GetNextInterval(interval time.Duration) time.Duration { - return minDuration(time.Duration(float64(interval)*ScheduleIntervalFactor), MaxScheduleInterval) -} - -func minDuration(a, b time.Duration) time.Duration { - if a < b { - return a - } - return b -} diff --git a/plugin/move_leader/user_config.go b/plugin/move_leader/user_config.go deleted file mode 100644 index e70ff40ff45..00000000000 --- a/plugin/move_leader/user_config.go +++ /dev/null @@ -1,136 +0,0 @@ -package main - -import ( - "path/filepath" - "strconv" - "sync" - "time" - - "github.com/pingcap/pd/server/schedule" - - "github.com/BurntSushi/toml" - "github.com/pingcap/log" - "go.uber.org/zap" -) - -type userConfig struct { - cfgLock sync.RWMutex - version uint64 - cfg *dispatchConfig -} - -type dispatchConfig struct { - Leaders leaders -} - -type leaders struct { - Leader []moveLeader -} - -type moveLeader struct { - KeyStart string - KeyEnd string - Stores []schedule.StoreLabels - StartTime time.Time - EndTime time.Time -} - -func NewUserConfig() schedule.Config { - ret := &userConfig{ - cfgLock: sync.RWMutex{}, - version: 1, - cfg: nil, - } - return ret -} - -// Load and decode config file -// if conflict, return false -// if not conflict, reset pluginInfoMap -func (uc *userConfig) LoadConfig(path string, maxReplicas int) bool { - filePath, err := filepath.Abs(path) - if err != nil { - log.Error("open file failed", zap.Error(err)) - return false - } - log.Info("parse toml file once. ", zap.String("filePath", filePath)) - cfg := new(dispatchConfig) - if _, err := toml.DecodeFile(filePath, cfg); err != nil { - log.Error("parse user config failed", zap.Error(err)) - return false - } - uc.cfgLock.Lock() - defer uc.cfgLock.Unlock() - schedule.PluginsInfoMapLock.Lock() - defer schedule.PluginsInfoMapLock.Unlock() - uc.cfg = cfg - if uc.cfg != nil && uc.IfConflict(maxReplicas) { - return false - } - schedule.PluginsInfoMap = make(map[string]*schedule.PluginInfo) - for i, info := range uc.cfg.Leaders.Leader { - pi := &schedule.PluginInfo{ - KeyStart: info.KeyStart, - KeyEnd: info.KeyEnd, - Interval: &schedule.TimeInterval{Begin: info.StartTime, End: info.EndTime}, - Stores: info.Stores, - StoreIDs: []uint64{}, - } - str := "Leader-" + strconv.Itoa(i) - schedule.PluginsInfoMap[str] = pi - } - uc.version++ - return true -} - -func (uc *userConfig) GetStoreId(cluster schedule.Cluster) map[string][]uint64 { - ret := make(map[string][]uint64) - for i, Leader := range uc.cfg.Leaders.Leader { - for _, s := range Leader.Stores { - if store := schedule.GetStoreByLabel(cluster, s.StoreLabel); store != nil { - str := "Leader-" + strconv.Itoa(i) - log.Info(str, zap.Uint64("store-id", store.GetID())) - ret[str] = append(ret[str], store.GetID()) - } - } - } - return ret -} - -func (uc *userConfig) GetInterval() map[string]*schedule.TimeInterval { - ret := make(map[string]*schedule.TimeInterval) - for i, Leader := range uc.cfg.Leaders.Leader { - str := "Leader-" + strconv.Itoa(i) - interval := &schedule.TimeInterval{ - Begin: Leader.StartTime, - End: Leader.EndTime, - } - ret[str] = interval - } - return ret -} - -// Check if there are conflicts in similar type of rules -// eg. move-leader&move-leader or move-region&move-region -func (uc *userConfig) IfConflict(maxReplicas int) bool { - ret := false - // move_leaders - for i, l1 := range uc.cfg.Leaders.Leader { - for j, l2 := range uc.cfg.Leaders.Leader { - if i < j { - if (l1.KeyStart <= l2.KeyStart && l1.KeyEnd > l2.KeyStart) || - (l2.KeyStart <= l1.KeyStart && l2.KeyEnd > l1.KeyStart) { - if ((l1.StartTime.Before(l2.StartTime) || l1.StartTime.Equal(l2.StartTime)) && - l1.EndTime.After(l2.StartTime)) || - ((l2.StartTime.Before(l1.StartTime) || l2.StartTime.Equal(l1.StartTime)) && - l2.EndTime.After(l1.StartTime)) { - log.Error("Key Range Conflict", zap.Ints("Config Move-Leader Nums", []int{i, j})) - ret = true - } - - } - } - } - } - return ret -}