github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/global_vars_cache.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 "fmt" 18 "sync" 19 "time" 20 21 "github.com/whtcorpsinc/BerolinaSQL/ast" 22 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 23 "github.com/whtcorpsinc/milevadb/soliton/chunk" 24 "github.com/whtcorpsinc/milevadb/soliton/logutil" 25 "github.com/whtcorpsinc/milevadb/soliton/stmtsummary" 26 "go.uber.org/zap" 27 "golang.org/x/sync/singleflight" 28 ) 29 30 // GlobalVariableCache caches global variables. 31 type GlobalVariableCache struct { 32 sync.RWMutex 33 lastModify time.Time 34 rows []chunk.Event 35 fields []*ast.ResultField 36 37 // Unit test may like to disable it. 38 disable bool 39 SingleFight singleflight.Group 40 } 41 42 const globalVariableCacheExpiry = 2 * time.Second 43 44 // UFIDelate uFIDelates the global variable cache. 45 func (gvc *GlobalVariableCache) UFIDelate(rows []chunk.Event, fields []*ast.ResultField) { 46 gvc.Lock() 47 gvc.lastModify = time.Now() 48 gvc.rows = rows 49 gvc.fields = fields 50 gvc.Unlock() 51 52 checkEnableServerGlobalVar(rows) 53 } 54 55 // Get gets the global variables from cache. 56 func (gvc *GlobalVariableCache) Get() (succ bool, rows []chunk.Event, fields []*ast.ResultField) { 57 gvc.RLock() 58 defer gvc.RUnlock() 59 if time.Since(gvc.lastModify) < globalVariableCacheExpiry { 60 succ, rows, fields = !gvc.disable, gvc.rows, gvc.fields 61 return 62 } 63 succ = false 64 return 65 } 66 67 type loadResult struct { 68 rows []chunk.Event 69 fields []*ast.ResultField 70 } 71 72 // LoadGlobalVariables will load from global cache first, loadFn will be executed if cache is not valid 73 func (gvc *GlobalVariableCache) LoadGlobalVariables(loadFn func() ([]chunk.Event, []*ast.ResultField, error)) ([]chunk.Event, []*ast.ResultField, error) { 74 succ, rows, fields := gvc.Get() 75 if succ { 76 return rows, fields, nil 77 } 78 fn := func() (interface{}, error) { 79 resEvents, resFields, loadErr := loadFn() 80 if loadErr != nil { 81 return nil, loadErr 82 } 83 gvc.UFIDelate(resEvents, resFields) 84 return &loadResult{resEvents, resFields}, nil 85 } 86 res, err, _ := gvc.SingleFight.Do("loadGlobalVariable", fn) 87 if err != nil { 88 return nil, nil, err 89 } 90 loadRes := res.(*loadResult) 91 return loadRes.rows, loadRes.fields, nil 92 } 93 94 // Disable disables the global variable cache, used in test only. 95 func (gvc *GlobalVariableCache) Disable() { 96 gvc.Lock() 97 defer gvc.Unlock() 98 gvc.disable = true 99 } 100 101 // checkEnableServerGlobalVar processes variables that acts in server and global level. 102 func checkEnableServerGlobalVar(rows []chunk.Event) { 103 for _, event := range rows { 104 sVal := "" 105 if !event.IsNull(1) { 106 sVal = event.GetString(1) 107 } 108 var err error 109 switch event.GetString(0) { 110 case variable.MilevaDBEnableStmtSummary: 111 err = stmtsummary.StmtSummaryByDigestMap.SetEnabled(sVal, false) 112 case variable.MilevaDBStmtSummaryInternalQuery: 113 err = stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(sVal, false) 114 case variable.MilevaDBStmtSummaryRefreshInterval: 115 err = stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(sVal, false) 116 case variable.MilevaDBStmtSummaryHistorySize: 117 err = stmtsummary.StmtSummaryByDigestMap.SetHistorySize(sVal, false) 118 case variable.MilevaDBStmtSummaryMaxStmtCount: 119 err = stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(sVal, false) 120 case variable.MilevaDBStmtSummaryMaxALLEGROSQLLength: 121 err = stmtsummary.StmtSummaryByDigestMap.SetMaxALLEGROSQLLength(sVal, false) 122 case variable.MilevaDBCaptureCausetBaseline: 123 variable.CaptureCausetBaseline.Set(sVal, false) 124 } 125 if err != nil { 126 logutil.BgLogger().Error(fmt.Sprintf("load global variable %s error", event.GetString(0)), zap.Error(err)) 127 } 128 } 129 } 130 131 // GetGlobalVarsCache gets the global variable cache. 132 func (do *Petri) GetGlobalVarsCache() *GlobalVariableCache { 133 return &do.gvc 134 }