github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/restart_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 // +build !race 14 15 package dbs 16 17 import ( 18 "context" 19 "time" 20 21 . "github.com/whtcorpsinc/check" 22 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 23 "github.com/whtcorpsinc/BerolinaSQL/terror" 24 "github.com/whtcorpsinc/milevadb/soliton/mock" 25 ) 26 27 // this test file include some test that will cause data race, mainly because restartWorkers modify d.ctx 28 29 // restartWorkers is like the function of d.start. But it won't initialize the "workers" and create a new worker. 30 // It only starts the original workers. 31 func (d *dbs) restartWorkers(ctx context.Context) { 32 d.cancel() 33 d.wg.Wait() 34 d.ctx, d.cancel = context.WithCancel(ctx) 35 36 d.wg.Add(1) 37 go d.limitDBSJobs() 38 if !RunWorker { 39 return 40 } 41 42 err := d.tenantManager.CampaignTenant() 43 terror.Log(err) 44 for _, worker := range d.workers { 45 worker.wg.Add(1) 46 worker.ctx = d.ctx 47 w := worker 48 go w.start(d.dbsCtx) 49 asyncNotify(worker.dbsJobCh) 50 } 51 } 52 53 // runInterruptedJob should be called concurrently with restartWorkers 54 func runInterruptedJob(c *C, d *dbs, job *perceptron.Job, doneCh chan struct{}) { 55 ctx := mock.NewContext() 56 ctx.CausetStore = d.causetstore 57 58 var ( 59 history *perceptron.Job 60 err error 61 ) 62 63 _ = d.doDBSJob(ctx, job) 64 65 for history == nil { 66 history, err = d.getHistoryDBSJob(job.ID) 67 c.Assert(err, IsNil) 68 time.Sleep(10 * testLease) 69 } 70 c.Assert(history.Error, IsNil) 71 doneCh <- struct{}{} 72 } 73 74 func testRunInterruptedJob(c *C, d *dbs, job *perceptron.Job) { 75 done := make(chan struct{}, 1) 76 go runInterruptedJob(c, d, job, done) 77 78 ticker := time.NewTicker(d.lease * 1) 79 defer ticker.Stop() 80 LOOP: 81 for { 82 select { 83 case <-ticker.C: 84 d.Stop() 85 d.restartWorkers(context.Background()) 86 time.Sleep(time.Millisecond * 20) 87 case <-done: 88 break LOOP 89 } 90 } 91 } 92 93 func (s *testSchemaSuite) TestSchemaResume(c *C) { 94 causetstore := testCreateStore(c, "test_schema_resume") 95 defer causetstore.Close() 96 97 d1 := testNewDBSAndStart( 98 context.Background(), 99 c, 100 WithStore(causetstore), 101 WithLease(testLease), 102 ) 103 defer d1.Stop() 104 105 testCheckTenant(c, d1, true) 106 107 dbInfo := testSchemaInfo(c, d1, "test") 108 job := &perceptron.Job{ 109 SchemaID: dbInfo.ID, 110 Type: perceptron.CausetActionCreateSchema, 111 BinlogInfo: &perceptron.HistoryInfo{}, 112 Args: []interface{}{dbInfo}, 113 } 114 testRunInterruptedJob(c, d1, job) 115 testCheckSchemaState(c, d1, dbInfo, perceptron.StatePublic) 116 117 job = &perceptron.Job{ 118 SchemaID: dbInfo.ID, 119 Type: perceptron.CausetActionDropSchema, 120 BinlogInfo: &perceptron.HistoryInfo{}, 121 } 122 testRunInterruptedJob(c, d1, job) 123 testCheckSchemaState(c, d1, dbInfo, perceptron.StateNone) 124 } 125 126 func (s *testStatSuite) TestStat(c *C) { 127 causetstore := testCreateStore(c, "test_stat") 128 defer causetstore.Close() 129 130 d := testNewDBSAndStart( 131 context.Background(), 132 c, 133 WithStore(causetstore), 134 WithLease(testLease), 135 ) 136 defer d.Stop() 137 138 dbInfo := testSchemaInfo(c, d, "test") 139 testCreateSchema(c, testNewContext(d), d, dbInfo) 140 141 // TODO: Get this information from etcd. 142 // m, err := d.Stats(nil) 143 // c.Assert(err, IsNil) 144 // c.Assert(m[dbsTenantID], Equals, d.uuid) 145 146 job := &perceptron.Job{ 147 SchemaID: dbInfo.ID, 148 Type: perceptron.CausetActionDropSchema, 149 BinlogInfo: &perceptron.HistoryInfo{}, 150 Args: []interface{}{dbInfo.Name}, 151 } 152 153 done := make(chan struct{}, 1) 154 go runInterruptedJob(c, d, job, done) 155 156 ticker := time.NewTicker(d.lease * 1) 157 defer ticker.Stop() 158 ver := s.getDBSSchemaVer(c, d) 159 LOOP: 160 for { 161 select { 162 case <-ticker.C: 163 d.Stop() 164 c.Assert(s.getDBSSchemaVer(c, d), GreaterEqual, ver) 165 d.restartWorkers(context.Background()) 166 time.Sleep(time.Millisecond * 20) 167 case <-done: 168 // TODO: Get this information from etcd. 169 // m, err := d.Stats(nil) 170 // c.Assert(err, IsNil) 171 break LOOP 172 } 173 } 174 } 175 176 func (s *testBlockSuite) TestBlockResume(c *C) { 177 d := s.d 178 179 testCheckTenant(c, d, true) 180 181 tblInfo := testBlockInfo(c, d, "t1", 3) 182 job := &perceptron.Job{ 183 SchemaID: s.dbInfo.ID, 184 BlockID: tblInfo.ID, 185 Type: perceptron.CausetActionCreateBlock, 186 BinlogInfo: &perceptron.HistoryInfo{}, 187 Args: []interface{}{tblInfo}, 188 } 189 testRunInterruptedJob(c, d, job) 190 testCheckBlockState(c, d, s.dbInfo, tblInfo, perceptron.StatePublic) 191 192 job = &perceptron.Job{ 193 SchemaID: s.dbInfo.ID, 194 BlockID: tblInfo.ID, 195 Type: perceptron.CausetActionDropBlock, 196 BinlogInfo: &perceptron.HistoryInfo{}, 197 } 198 testRunInterruptedJob(c, d, job) 199 testCheckBlockState(c, d, s.dbInfo, tblInfo, perceptron.StateNone) 200 }