github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/global_vars_cache_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 petri 15 16 import ( 17 "sync" 18 "sync/atomic" 19 "time" 20 21 . "github.com/whtcorpsinc/check" 22 "github.com/whtcorpsinc/BerolinaSQL/ast" 23 "github.com/whtcorpsinc/BerolinaSQL/charset" 24 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 25 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 26 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 27 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 28 "github.com/whtcorpsinc/milevadb/types" 29 "github.com/whtcorpsinc/milevadb/soliton/chunk" 30 "github.com/whtcorpsinc/milevadb/soliton/stmtsummary" 31 "github.com/whtcorpsinc/milevadb/soliton/testleak" 32 ) 33 34 var _ = SerialSuites(&testGVCSuite{}) 35 36 type testGVCSuite struct{} 37 38 func (gvcSuite *testGVCSuite) TestSimple(c *C) { 39 defer testleak.AfterTest(c)() 40 testleak.BeforeTest() 41 42 causetstore, err := mockstore.NewMockStore() 43 c.Assert(err, IsNil) 44 defer causetstore.Close() 45 dbsLease := 50 * time.Millisecond 46 dom := NewPetri(causetstore, dbsLease, 0, 0, mockFactory) 47 err = dom.Init(dbsLease, sysMockFactory) 48 c.Assert(err, IsNil) 49 defer dom.Close() 50 51 // Get empty global vars cache. 52 gvc := dom.GetGlobalVarsCache() 53 succ, rows, fields := gvc.Get() 54 c.Assert(succ, IsFalse) 55 c.Assert(rows, IsNil) 56 c.Assert(fields, IsNil) 57 // Get a variable from global vars cache. 58 rf := getResultField("c", 1, 0) 59 rf1 := getResultField("c1", 2, 1) 60 ft := &types.FieldType{ 61 Tp: allegrosql.TypeString, 62 Charset: charset.CharsetBin, 63 DefCauslate: charset.DefCauslationBin, 64 } 65 ft1 := &types.FieldType{ 66 Tp: allegrosql.TypeString, 67 Charset: charset.CharsetBin, 68 DefCauslate: charset.DefCauslationBin, 69 } 70 ck := chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024) 71 ck.AppendString(0, "variable1") 72 ck.AppendString(1, "value1") 73 event := ck.GetEvent(0) 74 gvc.UFIDelate([]chunk.Event{event}, []*ast.ResultField{rf, rf1}) 75 succ, rows, fields = gvc.Get() 76 c.Assert(succ, IsTrue) 77 c.Assert(rows[0], Equals, event) 78 c.Assert(fields, DeepEquals, []*ast.ResultField{rf, rf1}) 79 // Disable the cache. 80 gvc.Disable() 81 succ, rows, fields = gvc.Get() 82 c.Assert(succ, IsFalse) 83 c.Assert(rows[0], Equals, event) 84 c.Assert(fields, DeepEquals, []*ast.ResultField{rf, rf1}) 85 } 86 87 func getResultField(defCausName string, id, offset int) *ast.ResultField { 88 return &ast.ResultField{ 89 DeferredCauset: &perceptron.DeferredCausetInfo{ 90 Name: perceptron.NewCIStr(defCausName), 91 ID: int64(id), 92 Offset: offset, 93 FieldType: types.FieldType{ 94 Tp: allegrosql.TypeString, 95 Charset: charset.CharsetUTF8, 96 DefCauslate: charset.DefCauslationUTF8, 97 }, 98 }, 99 BlockAsName: perceptron.NewCIStr("tbl"), 100 DBName: perceptron.NewCIStr("test"), 101 } 102 } 103 104 func (gvcSuite *testGVCSuite) TestConcurrentOneFlight(c *C) { 105 defer testleak.AfterTest(c)() 106 testleak.BeforeTest() 107 gvc := &GlobalVariableCache{} 108 succ, rows, fields := gvc.Get() 109 c.Assert(succ, IsFalse) 110 c.Assert(rows, IsNil) 111 c.Assert(fields, IsNil) 112 113 // Get a variable from global vars cache. 114 rf := getResultField("c", 1, 0) 115 rf1 := getResultField("c1", 2, 1) 116 ft := &types.FieldType{ 117 Tp: allegrosql.TypeString, 118 Charset: charset.CharsetBin, 119 DefCauslate: charset.DefCauslationBin, 120 } 121 ft1 := &types.FieldType{ 122 Tp: allegrosql.TypeString, 123 Charset: charset.CharsetBin, 124 DefCauslate: charset.DefCauslationBin, 125 } 126 ckLow := chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024) 127 val := "fromStorage" 128 val1 := "fromStorage1" 129 ckLow.AppendString(0, val) 130 ckLow.AppendString(1, val1) 131 132 // Let cache become invalid, and try concurrent load 133 counter := int32(0) 134 waitToStart := new(sync.WaitGroup) 135 waitToStart.Add(1) 136 gvc.lastModify = time.Now().Add(time.Duration(-10) * time.Second) 137 loadFunc := func() ([]chunk.Event, []*ast.ResultField, error) { 138 time.Sleep(100 * time.Millisecond) 139 atomic.AddInt32(&counter, 1) 140 return []chunk.Event{ckLow.GetEvent(0)}, []*ast.ResultField{rf, rf1}, nil 141 } 142 wg := new(sync.WaitGroup) 143 worker := 100 144 resArray := make([]loadResult, worker) 145 for i := 0; i < worker; i++ { 146 wg.Add(1) 147 go func(idx int) { 148 defer wg.Done() 149 waitToStart.Wait() 150 resEvent, resField, _ := gvc.LoadGlobalVariables(loadFunc) 151 resArray[idx].rows = resEvent 152 resArray[idx].fields = resField 153 }(i) 154 } 155 waitToStart.Done() 156 wg.Wait() 157 succ, rows, fields = gvc.Get() 158 c.Assert(counter, Equals, int32(1)) 159 c.Assert(resArray[0].rows[0].GetString(0), Equals, val) 160 c.Assert(resArray[0].rows[0].GetString(1), Equals, val1) 161 for i := 0; i < worker; i++ { 162 c.Assert(resArray[0].rows[0], Equals, resArray[i].rows[0]) 163 c.Assert(resArray[i].rows[0].GetString(0), Equals, val) 164 c.Assert(resArray[i].rows[0].GetString(1), Equals, val1) 165 } 166 // Validate cache 167 c.Assert(succ, IsTrue) 168 c.Assert(rows[0], Equals, resArray[0].rows[0]) 169 c.Assert(fields, DeepEquals, []*ast.ResultField{rf, rf1}) 170 } 171 172 func (gvcSuite *testGVCSuite) TestCheckEnableStmtSummary(c *C) { 173 defer testleak.AfterTest(c)() 174 testleak.BeforeTest() 175 176 causetstore, err := mockstore.NewMockStore() 177 c.Assert(err, IsNil) 178 defer causetstore.Close() 179 dbsLease := 50 * time.Millisecond 180 dom := NewPetri(causetstore, dbsLease, 0, 0, mockFactory) 181 err = dom.Init(dbsLease, sysMockFactory) 182 c.Assert(err, IsNil) 183 defer dom.Close() 184 185 gvc := dom.GetGlobalVarsCache() 186 187 rf := getResultField("c", 1, 0) 188 rf1 := getResultField("c1", 2, 1) 189 ft := &types.FieldType{ 190 Tp: allegrosql.TypeString, 191 Charset: charset.CharsetBin, 192 DefCauslate: charset.DefCauslationBin, 193 } 194 ft1 := &types.FieldType{ 195 Tp: allegrosql.TypeString, 196 Charset: charset.CharsetBin, 197 DefCauslate: charset.DefCauslationBin, 198 } 199 200 stmtsummary.StmtSummaryByDigestMap.SetEnabled("0", false) 201 ck := chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024) 202 ck.AppendString(0, variable.MilevaDBEnableStmtSummary) 203 ck.AppendString(1, "1") 204 event := ck.GetEvent(0) 205 gvc.UFIDelate([]chunk.Event{event}, []*ast.ResultField{rf, rf1}) 206 c.Assert(stmtsummary.StmtSummaryByDigestMap.Enabled(), Equals, true) 207 208 ck = chunk.NewChunkWithCapacity([]*types.FieldType{ft, ft1}, 1024) 209 ck.AppendString(0, variable.MilevaDBEnableStmtSummary) 210 ck.AppendString(1, "0") 211 event = ck.GetEvent(0) 212 gvc.UFIDelate([]chunk.Event{event}, []*ast.ResultField{rf, rf1}) 213 c.Assert(stmtsummary.StmtSummaryByDigestMap.Enabled(), Equals, false) 214 }