Skip to content

Commit 4033f6e

Browse files
okJiangti-chi-bot
authored andcommitted
This is an automated cherry-pick of tikv#8757
close tikv#8756 Signed-off-by: ti-chi-bot <[email protected]>
1 parent d347eed commit 4033f6e

File tree

6 files changed

+509
-0
lines changed

6 files changed

+509
-0
lines changed

pkg/core/store.go

+23
Original file line numberDiff line numberDiff line change
@@ -663,8 +663,24 @@ func (s *StoresInfo) SetStore(store *StoreInfo) {
663663
s.stores[store.GetID()] = store
664664
}
665665

666+
<<<<<<< HEAD
666667
// PauseLeaderTransfer pauses a StoreInfo with storeID.
667668
func (s *StoresInfo) PauseLeaderTransfer(storeID uint64) error {
669+
=======
670+
// ResetStores resets the store cache.
671+
func (s *StoresInfo) ResetStores() {
672+
s.Lock()
673+
defer s.Unlock()
674+
s.stores = make(map[uint64]*StoreInfo)
675+
}
676+
677+
// PauseLeaderTransfer pauses a StoreInfo with storeID. The store can not be selected
678+
// as source or target of TransferLeader.
679+
func (s *StoresInfo) PauseLeaderTransfer(storeID uint64, direction constant.Direction) error {
680+
s.Lock()
681+
defer s.Unlock()
682+
log.Info("pause store leader transfer", zap.Uint64("store-id", storeID), zap.String("direction", direction.String()))
683+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
668684
store, ok := s.stores[storeID]
669685
if !ok {
670686
return errs.ErrStoreNotFound.FastGenByArgs(storeID)
@@ -678,7 +694,14 @@ func (s *StoresInfo) PauseLeaderTransfer(storeID uint64) error {
678694

679695
// ResumeLeaderTransfer cleans a store's pause state. The store can be selected
680696
// as source or target of TransferLeader again.
697+
<<<<<<< HEAD
681698
func (s *StoresInfo) ResumeLeaderTransfer(storeID uint64) {
699+
=======
700+
func (s *StoresInfo) ResumeLeaderTransfer(storeID uint64, direction constant.Direction) {
701+
s.Lock()
702+
defer s.Unlock()
703+
log.Info("resume store leader transfer", zap.Uint64("store-id", storeID), zap.String("direction", direction.String()))
704+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
682705
store, ok := s.stores[storeID]
683706
if !ok {
684707
log.Warn("try to clean a store's pause state, but it is not found. It may be cleanup",

pkg/schedule/schedulers/grant_leader.go

+12
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ type grantLeaderSchedulerConfig struct {
5555
cluster schedule.Cluster
5656
}
5757

58+
<<<<<<< HEAD
5859
func (conf *grantLeaderSchedulerConfig) BuildWithArgs(args []string) error {
60+
=======
61+
func (conf *grantLeaderSchedulerConfig) buildWithArgs(args []string) error {
62+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
5963
if len(args) < 1 {
6064
return errs.ErrSchedulerConfig.FastGenByArgs("id")
6165
}
@@ -269,14 +273,22 @@ func (handler *grantLeaderHandler) UpdateConfig(w http.ResponseWriter, r *http.R
269273

270274
err := handler.config.BuildWithArgs(args)
271275
if err != nil {
276+
<<<<<<< HEAD
272277
handler.config.mu.Lock()
273278
handler.config.cluster.ResumeLeaderTransfer(id)
274279
handler.config.mu.Unlock()
280+
=======
281+
log.Error("fail to build config", errs.ZapError(err))
282+
handler.config.Lock()
283+
handler.config.cluster.ResumeLeaderTransfer(id, constant.Out)
284+
handler.config.Unlock()
285+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
275286
handler.rd.JSON(w, http.StatusBadRequest, err.Error())
276287
return
277288
}
278289
err = handler.config.Persist()
279290
if err != nil {
291+
log.Error("fail to persist config", errs.ZapError(err))
280292
_, _ = handler.config.removeStore(id)
281293
handler.rd.JSON(w, http.StatusInternalServerError, err.Error())
282294
return

pkg/schedule/schedulers/init.go

+10
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,13 @@ func schedulersRegister() {
117117
})
118118

119119
// evict leader
120+
<<<<<<< HEAD
120121
schedule.RegisterSliceDecoderBuilder(EvictLeaderType, func(args []string) schedule.ConfigDecoder {
121122
return func(v interface{}) error {
123+
=======
124+
RegisterSliceDecoderBuilder(types.EvictLeaderScheduler, func(args []string) ConfigDecoder {
125+
return func(v any) error {
126+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
122127
if len(args) < 1 {
123128
return errs.ErrSchedulerConfig.FastGenByArgs("id")
124129
}
@@ -233,8 +238,13 @@ func schedulersRegister() {
233238
})
234239

235240
// grant leader
241+
<<<<<<< HEAD
236242
schedule.RegisterSliceDecoderBuilder(GrantLeaderType, func(args []string) schedule.ConfigDecoder {
237243
return func(v interface{}) error {
244+
=======
245+
RegisterSliceDecoderBuilder(types.GrantLeaderScheduler, func(args []string) ConfigDecoder {
246+
return func(v any) error {
247+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
238248
if len(args) < 1 {
239249
return errs.ErrSchedulerConfig.FastGenByArgs("id")
240250
}

plugin/scheduler_example/evict_leader.go

+5
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,13 @@ const (
4545
)
4646

4747
func init() {
48+
<<<<<<< HEAD
4849
schedule.RegisterSliceDecoderBuilder(EvictLeaderType, func(args []string) schedule.ConfigDecoder {
4950
return func(v interface{}) error {
51+
=======
52+
schedulers.RegisterSliceDecoderBuilder(userEvictLeaderScheduler, func(args []string) schedulers.ConfigDecoder {
53+
return func(v any) error {
54+
>>>>>>> 90cc61b43 (scheduler: add test for creating evict-leader-scheduler twice (#8757))
5055
if len(args) < 1 {
5156
return errors.New("should specify the store-id")
5257
}
+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright 2024 TiKV Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package realcluster
16+
17+
import (
18+
"fmt"
19+
"os"
20+
"os/exec"
21+
"path/filepath"
22+
"strings"
23+
"testing"
24+
"time"
25+
26+
"github.com/pingcap/log"
27+
"github.com/stretchr/testify/require"
28+
"github.com/stretchr/testify/suite"
29+
"go.uber.org/zap"
30+
)
31+
32+
type clusterSuite struct {
33+
suite.Suite
34+
35+
clusterCnt int
36+
suiteName string
37+
ms bool
38+
}
39+
40+
var (
41+
playgroundLogDir = "/tmp/real_cluster/playground"
42+
tiupBin = os.Getenv("HOME") + "/.tiup/bin/tiup"
43+
)
44+
45+
// SetupSuite will run before the tests in the suite are run.
46+
func (s *clusterSuite) SetupSuite() {
47+
t := s.T()
48+
49+
// Clean the data dir. It is the default data dir of TiUP.
50+
dataDir := filepath.Join(os.Getenv("HOME"), ".tiup", "data", "pd_real_cluster_test_"+s.suiteName+"_*")
51+
matches, err := filepath.Glob(dataDir)
52+
require.NoError(t, err)
53+
54+
for _, match := range matches {
55+
require.NoError(t, runCommand("rm", "-rf", match))
56+
}
57+
s.startCluster(t)
58+
t.Cleanup(func() {
59+
s.stopCluster(t)
60+
})
61+
}
62+
63+
// TearDownSuite will run after all the tests in the suite have been run.
64+
func (s *clusterSuite) TearDownSuite() {
65+
// Even if the cluster deployment fails, we still need to destroy the cluster.
66+
// If the cluster does not fail to deploy, the cluster will be destroyed in
67+
// the cleanup function. And these code will not work.
68+
s.clusterCnt++
69+
s.stopCluster(s.T())
70+
}
71+
72+
func (s *clusterSuite) startCluster(t *testing.T) {
73+
log.Info("start to deploy a cluster", zap.Bool("ms", s.ms))
74+
75+
tag := s.tag()
76+
deployTiupPlayground(t, tag, s.ms)
77+
waitTiupReady(t, tag)
78+
s.clusterCnt++
79+
}
80+
81+
func (s *clusterSuite) stopCluster(t *testing.T) {
82+
s.clusterCnt--
83+
84+
log.Info("start to destroy a cluster", zap.String("tag", s.tag()), zap.Bool("ms", s.ms))
85+
destroy(t, s.tag())
86+
time.Sleep(5 * time.Second)
87+
}
88+
89+
func (s *clusterSuite) tag() string {
90+
return fmt.Sprintf("pd_real_cluster_test_%s_%d", s.suiteName, s.clusterCnt)
91+
}
92+
93+
func (s *clusterSuite) restart() {
94+
tag := s.tag()
95+
log.Info("start to restart", zap.String("tag", tag))
96+
s.stopCluster(s.T())
97+
s.startCluster(s.T())
98+
log.Info("TiUP restart success")
99+
}
100+
101+
func destroy(t *testing.T, tag string) {
102+
cmdStr := fmt.Sprintf("ps -ef | grep %s | awk '{print $2}'", tag)
103+
cmd := exec.Command("sh", "-c", cmdStr)
104+
bytes, err := cmd.Output()
105+
require.NoError(t, err)
106+
pids := string(bytes)
107+
pidArr := strings.Split(pids, "\n")
108+
for _, pid := range pidArr {
109+
// nolint:errcheck
110+
runCommand("sh", "-c", "kill -9 "+pid)
111+
}
112+
log.Info("destroy success", zap.String("tag", tag))
113+
}
114+
115+
func deployTiupPlayground(t *testing.T, tag string, ms bool) {
116+
curPath, err := os.Getwd()
117+
require.NoError(t, err)
118+
require.NoError(t, os.Chdir("../../.."))
119+
120+
if !fileExists("third_bin") || !fileExists("third_bin/tikv-server") || !fileExists("third_bin/tidb-server") || !fileExists("third_bin/tiflash") {
121+
log.Info("downloading binaries...")
122+
log.Info("this may take a few minutes, you can also download them manually and put them in the bin directory.")
123+
require.NoError(t, runCommand("sh",
124+
"./tests/integrations/realcluster/download_integration_test_binaries.sh"))
125+
}
126+
if !fileExists("bin") || !fileExists("bin/pd-server") {
127+
log.Info("complie pd binaries...")
128+
require.NoError(t, runCommand("make", "pd-server"))
129+
}
130+
131+
if !fileExists(playgroundLogDir) {
132+
require.NoError(t, os.MkdirAll(playgroundLogDir, 0755))
133+
}
134+
135+
// nolint:errcheck
136+
go func() {
137+
if ms {
138+
runCommand("sh", "-c",
139+
tiupBin+` playground nightly --pd.mode ms --kv 3 --tiflash 1 --db 1 --pd 3 --tso 1 --scheduling 1 \
140+
--without-monitor --tag `+tag+` \
141+
--pd.binpath ./bin/pd-server \
142+
--kv.binpath ./third_bin/tikv-server \
143+
--db.binpath ./third_bin/tidb-server \
144+
--tiflash.binpath ./third_bin/tiflash \
145+
--tso.binpath ./bin/pd-server \
146+
--scheduling.binpath ./bin/pd-server \
147+
--pd.config ./tests/integrations/realcluster/pd.toml \
148+
> `+filepath.Join(playgroundLogDir, tag+".log")+` 2>&1 & `)
149+
} else {
150+
runCommand("sh", "-c",
151+
tiupBin+` playground nightly --kv 3 --tiflash 1 --db 1 --pd 3 \
152+
--without-monitor --tag `+tag+` \
153+
--pd.binpath ./bin/pd-server \
154+
--kv.binpath ./third_bin/tikv-server \
155+
--db.binpath ./third_bin/tidb-server \
156+
--tiflash.binpath ./third_bin/tiflash \
157+
--pd.config ./tests/integrations/realcluster/pd.toml \
158+
> `+filepath.Join(playgroundLogDir, tag+".log")+` 2>&1 & `)
159+
}
160+
}()
161+
162+
// Avoid to change the dir before execute `tiup playground`.
163+
time.Sleep(10 * time.Second)
164+
require.NoError(t, os.Chdir(curPath))
165+
}
166+
167+
func waitTiupReady(t *testing.T, tag string) {
168+
const (
169+
interval = 5
170+
maxTimes = 20
171+
)
172+
log.Info("start to wait TiUP ready", zap.String("tag", tag))
173+
for i := range maxTimes {
174+
err := runCommand(tiupBin, "playground", "display", "--tag", tag)
175+
if err == nil {
176+
log.Info("TiUP is ready", zap.String("tag", tag))
177+
return
178+
}
179+
180+
log.Info("TiUP is not ready, will retry", zap.Int("retry times", i),
181+
zap.String("tag", tag), zap.Error(err))
182+
time.Sleep(time.Duration(interval) * time.Second)
183+
}
184+
require.Failf(t, "TiUP is not ready", "tag: %s", tag)
185+
}

0 commit comments

Comments
 (0)