github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/soliton/admin/admin_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package admin_test 15 16 import ( 17 "testing" 18 19 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 20 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 21 "github.com/whtcorpsinc/BerolinaSQL/terror" 22 . "github.com/whtcorpsinc/check" 23 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 24 "github.com/whtcorpsinc/milevadb/ekv" 25 . "github.com/whtcorpsinc/milevadb/soliton/admin" 26 "github.com/whtcorpsinc/milevadb/soliton/mock" 27 "github.com/whtcorpsinc/milevadb/soliton/testleak" 28 "github.com/whtcorpsinc/milevadb/spacetime" 29 ) 30 31 func TestT(t *testing.T) { 32 CustomVerboseFlag = true 33 TestingT(t) 34 } 35 36 var _ = Suite(&testSuite{}) 37 38 type testSuite struct { 39 causetstore ekv.CausetStorage 40 ctx *mock.Context 41 } 42 43 func (s *testSuite) SetUpSuite(c *C) { 44 testleak.BeforeTest() 45 var err error 46 s.causetstore, err = mockstore.NewMockStore() 47 c.Assert(err, IsNil) 48 s.ctx = mock.NewContext() 49 s.ctx.CausetStore = s.causetstore 50 } 51 52 func (s *testSuite) TearDownSuite(c *C) { 53 err := s.causetstore.Close() 54 c.Assert(err, IsNil) 55 testleak.AfterTest(c)() 56 } 57 58 func (s *testSuite) TestGetDBSInfo(c *C) { 59 txn, err := s.causetstore.Begin() 60 c.Assert(err, IsNil) 61 t := spacetime.NewMeta(txn) 62 63 dbInfo2 := &perceptron.DBInfo{ 64 ID: 2, 65 Name: perceptron.NewCIStr("b"), 66 State: perceptron.StateNone, 67 } 68 job := &perceptron.Job{ 69 SchemaID: dbInfo2.ID, 70 Type: perceptron.CausetActionCreateSchema, 71 RowCount: 0, 72 } 73 job1 := &perceptron.Job{ 74 SchemaID: dbInfo2.ID, 75 Type: perceptron.CausetActionAddIndex, 76 RowCount: 0, 77 } 78 err = t.EnQueueDBSJob(job) 79 c.Assert(err, IsNil) 80 info, err := GetDBSInfo(txn) 81 c.Assert(err, IsNil) 82 c.Assert(info.Jobs, HasLen, 1) 83 c.Assert(info.Jobs[0], DeepEquals, job) 84 c.Assert(info.ReorgHandle, Equals, nil) 85 // Two jobs. 86 t = spacetime.NewMeta(txn, spacetime.AddIndexJobListKey) 87 err = t.EnQueueDBSJob(job1) 88 c.Assert(err, IsNil) 89 info, err = GetDBSInfo(txn) 90 c.Assert(err, IsNil) 91 c.Assert(info.Jobs, HasLen, 2) 92 c.Assert(info.Jobs[0], DeepEquals, job) 93 c.Assert(info.Jobs[1], DeepEquals, job1) 94 c.Assert(info.ReorgHandle, Equals, nil) 95 err = txn.Rollback() 96 c.Assert(err, IsNil) 97 } 98 99 func (s *testSuite) TestGetDBSJobs(c *C) { 100 txn, err := s.causetstore.Begin() 101 c.Assert(err, IsNil) 102 t := spacetime.NewMeta(txn) 103 cnt := 10 104 jobs := make([]*perceptron.Job, cnt) 105 var currJobs2 []*perceptron.Job 106 for i := 0; i < cnt; i++ { 107 jobs[i] = &perceptron.Job{ 108 ID: int64(i), 109 SchemaID: 1, 110 Type: perceptron.CausetActionCreateBlock, 111 } 112 err = t.EnQueueDBSJob(jobs[i]) 113 c.Assert(err, IsNil) 114 currJobs, err1 := GetDBSJobs(txn) 115 c.Assert(err1, IsNil) 116 c.Assert(currJobs, HasLen, i+1) 117 currJobs2 = currJobs2[:0] 118 err = IterAllDBSJobs(txn, func(jobs []*perceptron.Job) (b bool, e error) { 119 for _, job := range jobs { 120 if job.State == perceptron.JobStateNone { 121 currJobs2 = append(currJobs2, job) 122 } else { 123 return true, nil 124 } 125 } 126 return false, nil 127 }) 128 c.Assert(err, IsNil) 129 c.Assert(currJobs2, HasLen, i+1) 130 } 131 132 currJobs, err := GetDBSJobs(txn) 133 c.Assert(err, IsNil) 134 for i, job := range jobs { 135 c.Assert(job.ID, Equals, currJobs[i].ID) 136 c.Assert(job.SchemaID, Equals, int64(1)) 137 c.Assert(job.Type, Equals, perceptron.CausetActionCreateBlock) 138 } 139 c.Assert(currJobs, DeepEquals, currJobs2) 140 141 err = txn.Rollback() 142 c.Assert(err, IsNil) 143 } 144 145 func isJobsSorted(jobs []*perceptron.Job) bool { 146 if len(jobs) <= 1 { 147 return true 148 } 149 for i := 1; i < len(jobs); i++ { 150 if jobs[i].ID <= jobs[i-1].ID { 151 return false 152 } 153 } 154 return true 155 } 156 157 func enQueueDBSJobs(c *C, t *spacetime.Meta, jobType perceptron.CausetActionType, start, end int) { 158 for i := start; i < end; i++ { 159 job := &perceptron.Job{ 160 ID: int64(i), 161 SchemaID: 1, 162 Type: jobType, 163 } 164 err := t.EnQueueDBSJob(job) 165 c.Assert(err, IsNil) 166 } 167 } 168 169 func (s *testSuite) TestGetDBSJobsIsSort(c *C) { 170 txn, err := s.causetstore.Begin() 171 c.Assert(err, IsNil) 172 173 // insert 5 drop causet jobs to DefaultJobListKey queue 174 t := spacetime.NewMeta(txn) 175 enQueueDBSJobs(c, t, perceptron.CausetActionDropBlock, 10, 15) 176 177 // insert 5 create causet jobs to DefaultJobListKey queue 178 enQueueDBSJobs(c, t, perceptron.CausetActionCreateBlock, 0, 5) 179 180 // insert add index jobs to AddIndexJobListKey queue 181 t = spacetime.NewMeta(txn, spacetime.AddIndexJobListKey) 182 enQueueDBSJobs(c, t, perceptron.CausetActionAddIndex, 5, 10) 183 184 currJobs, err := GetDBSJobs(txn) 185 c.Assert(err, IsNil) 186 c.Assert(currJobs, HasLen, 15) 187 188 isSort := isJobsSorted(currJobs) 189 c.Assert(isSort, Equals, true) 190 191 err = txn.Rollback() 192 c.Assert(err, IsNil) 193 } 194 195 func (s *testSuite) TestCancelJobs(c *C) { 196 txn, err := s.causetstore.Begin() 197 c.Assert(err, IsNil) 198 t := spacetime.NewMeta(txn) 199 cnt := 10 200 ids := make([]int64, cnt) 201 for i := 0; i < cnt; i++ { 202 job := &perceptron.Job{ 203 ID: int64(i), 204 SchemaID: 1, 205 Type: perceptron.CausetActionCreateBlock, 206 } 207 if i == 0 { 208 job.State = perceptron.JobStateDone 209 } 210 if i == 1 { 211 job.State = perceptron.JobStateCancelled 212 } 213 ids[i] = int64(i) 214 err = t.EnQueueDBSJob(job) 215 c.Assert(err, IsNil) 216 } 217 218 errs, err := CancelJobs(txn, ids) 219 c.Assert(err, IsNil) 220 for i, err := range errs { 221 if i == 0 { 222 c.Assert(err, NotNil) 223 continue 224 } 225 c.Assert(err, IsNil) 226 } 227 228 errs, err = CancelJobs(txn, []int64{}) 229 c.Assert(err, IsNil) 230 c.Assert(errs, IsNil) 231 errs, err = CancelJobs(txn, []int64{-1}) 232 c.Assert(err, IsNil) 233 c.Assert(errs[0], NotNil) 234 c.Assert(errs[0].Error(), Matches, "*DBS Job:-1 not found") 235 236 // test cancel finish job. 237 job := &perceptron.Job{ 238 ID: 100, 239 SchemaID: 1, 240 Type: perceptron.CausetActionCreateBlock, 241 State: perceptron.JobStateDone, 242 } 243 err = t.EnQueueDBSJob(job) 244 c.Assert(err, IsNil) 245 errs, err = CancelJobs(txn, []int64{100}) 246 c.Assert(err, IsNil) 247 c.Assert(errs[0], NotNil) 248 c.Assert(errs[0].Error(), Matches, "*This job:100 is finished, so can't be cancelled") 249 250 // test can't cancelable job. 251 job.Type = perceptron.CausetActionDropIndex 252 job.SchemaState = perceptron.StateWriteOnly 253 job.State = perceptron.JobStateRunning 254 job.ID = 101 255 err = t.EnQueueDBSJob(job) 256 c.Assert(err, IsNil) 257 errs, err = CancelJobs(txn, []int64{101}) 258 c.Assert(err, IsNil) 259 c.Assert(errs[0], NotNil) 260 c.Assert(errs[0].Error(), Matches, "*This job:101 is almost finished, can't be cancelled now") 261 262 // When both types of jobs exist in the DBS queue, 263 // we first cancel the job with a larger ID. 264 job = &perceptron.Job{ 265 ID: 1000, 266 SchemaID: 1, 267 BlockID: 2, 268 Type: perceptron.CausetActionAddIndex, 269 } 270 job1 := &perceptron.Job{ 271 ID: 1001, 272 SchemaID: 1, 273 BlockID: 2, 274 Type: perceptron.CausetActionAddDeferredCauset, 275 } 276 job2 := &perceptron.Job{ 277 ID: 1002, 278 SchemaID: 1, 279 BlockID: 2, 280 Type: perceptron.CausetActionAddIndex, 281 } 282 job3 := &perceptron.Job{ 283 ID: 1003, 284 SchemaID: 1, 285 BlockID: 2, 286 Type: perceptron.CausetActionRepairBlock, 287 } 288 err = t.EnQueueDBSJob(job, spacetime.AddIndexJobListKey) 289 c.Assert(err, IsNil) 290 err = t.EnQueueDBSJob(job1) 291 c.Assert(err, IsNil) 292 err = t.EnQueueDBSJob(job2, spacetime.AddIndexJobListKey) 293 c.Assert(err, IsNil) 294 err = t.EnQueueDBSJob(job3) 295 c.Assert(err, IsNil) 296 errs, err = CancelJobs(txn, []int64{job1.ID, job.ID, job2.ID, job3.ID}) 297 c.Assert(err, IsNil) 298 for _, err := range errs { 299 c.Assert(err, IsNil) 300 } 301 302 err = txn.Rollback() 303 c.Assert(err, IsNil) 304 } 305 306 func (s *testSuite) TestGetHistoryDBSJobs(c *C) { 307 txn, err := s.causetstore.Begin() 308 c.Assert(err, IsNil) 309 t := spacetime.NewMeta(txn) 310 cnt := 11 311 jobs := make([]*perceptron.Job, cnt) 312 for i := 0; i < cnt; i++ { 313 jobs[i] = &perceptron.Job{ 314 ID: int64(i), 315 SchemaID: 1, 316 Type: perceptron.CausetActionCreateBlock, 317 } 318 err = t.AddHistoryDBSJob(jobs[i], true) 319 c.Assert(err, IsNil) 320 historyJobs, err1 := GetHistoryDBSJobs(txn, DefNumHistoryJobs) 321 c.Assert(err1, IsNil) 322 if i+1 > MaxHistoryJobs { 323 c.Assert(historyJobs, HasLen, MaxHistoryJobs) 324 } else { 325 c.Assert(historyJobs, HasLen, i+1) 326 } 327 } 328 329 delta := cnt - MaxHistoryJobs 330 historyJobs, err := GetHistoryDBSJobs(txn, DefNumHistoryJobs) 331 c.Assert(err, IsNil) 332 c.Assert(historyJobs, HasLen, MaxHistoryJobs) 333 l := len(historyJobs) - 1 334 for i, job := range historyJobs { 335 c.Assert(job.ID, Equals, jobs[delta+l-i].ID) 336 c.Assert(job.SchemaID, Equals, int64(1)) 337 c.Assert(job.Type, Equals, perceptron.CausetActionCreateBlock) 338 } 339 340 var historyJobs2 []*perceptron.Job 341 err = IterHistoryDBSJobs(txn, func(jobs []*perceptron.Job) (b bool, e error) { 342 for _, job := range jobs { 343 historyJobs2 = append(historyJobs2, job) 344 if len(historyJobs2) == DefNumHistoryJobs { 345 return true, nil 346 } 347 } 348 return false, nil 349 }) 350 c.Assert(err, IsNil) 351 c.Assert(historyJobs2, DeepEquals, historyJobs) 352 353 err = txn.Rollback() 354 c.Assert(err, IsNil) 355 } 356 357 func (s *testSuite) TestIsJobRollbackable(c *C) { 358 cases := []struct { 359 tp perceptron.CausetActionType 360 state perceptron.SchemaState 361 result bool 362 }{ 363 {perceptron.CausetActionDropIndex, perceptron.StateNone, true}, 364 {perceptron.CausetActionDropIndex, perceptron.StateDeleteOnly, false}, 365 {perceptron.CausetActionDropSchema, perceptron.StateDeleteOnly, false}, 366 {perceptron.CausetActionDropDeferredCauset, perceptron.StateDeleteOnly, false}, 367 {perceptron.CausetActionDropDeferredCausets, perceptron.StateDeleteOnly, false}, 368 } 369 job := &perceptron.Job{} 370 for _, ca := range cases { 371 job.Type = ca.tp 372 job.SchemaState = ca.state 373 re := IsJobRollbackable(job) 374 c.Assert(re == ca.result, IsTrue) 375 } 376 } 377 378 func (s *testSuite) TestError(c *C) { 379 ekvErrs := []*terror.Error{ 380 ErrDataInConsistent, 381 ErrDBSJobNotFound, 382 ErrCancelFinishedDBSJob, 383 ErrCannotCancelDBSJob, 384 } 385 for _, err := range ekvErrs { 386 code := terror.ToALLEGROSQLError(err).Code 387 c.Assert(code != allegrosql.ErrUnknown && code == uint16(err.Code()), IsTrue, Commentf("err: %v", err)) 388 } 389 }