github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/soliton/memory/action.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 memory 15 16 import ( 17 "fmt" 18 "sync" 19 20 "github.com/whtcorpsinc/BerolinaSQL/terror" 21 "github.com/whtcorpsinc/milevadb/errno" 22 "github.com/whtcorpsinc/milevadb/soliton/logutil" 23 "go.uber.org/zap" 24 ) 25 26 // SuperCowOrNoCausetOnExceed is the action taken when memory usage exceeds memory quota. 27 // NOTE: All the implementors should be thread-safe. 28 type SuperCowOrNoCausetOnExceed interface { 29 // CausetAction will be called when memory usage exceeds memory quota by the 30 // corresponding Tracker. 31 CausetAction(t *Tracker) 32 // SetLogHook binds a log hook which will be triggered and log an detailed 33 // message for the out-of-memory allegrosql. 34 SetLogHook(hook func(uint64)) 35 // SetFallback sets a fallback action which will be triggered if itself has 36 // already been triggered. 37 SetFallback(a SuperCowOrNoCausetOnExceed) 38 } 39 40 // RepLogCausetOnExceed logs a warning only once when memory usage exceeds memory quota. 41 type RepLogCausetOnExceed struct { 42 mutex sync.Mutex // For synchronization. 43 acted bool 44 ConnID uint64 45 logHook func(uint64) 46 } 47 48 // SetLogHook sets a hook for RepLogCausetOnExceed. 49 func (a *RepLogCausetOnExceed) SetLogHook(hook func(uint64)) { 50 a.logHook = hook 51 } 52 53 // CausetAction logs a warning only once when memory usage exceeds memory quota. 54 func (a *RepLogCausetOnExceed) CausetAction(t *Tracker) { 55 a.mutex.Lock() 56 defer a.mutex.Unlock() 57 if !a.acted { 58 a.acted = true 59 if a.logHook == nil { 60 logutil.BgLogger().Warn("memory exceeds quota", 61 zap.Error(errMemExceedThreshold.GenWithStackByArgs(t.label, t.BytesConsumed(), t.bytesLimit, t.String()))) 62 return 63 } 64 a.logHook(a.ConnID) 65 } 66 } 67 68 // SetFallback sets a fallback action. 69 func (a *RepLogCausetOnExceed) SetFallback(SuperCowOrNoCausetOnExceed) {} 70 71 // PanicOnExceed panics when memory usage exceeds memory quota. 72 type PanicOnExceed struct { 73 mutex sync.Mutex // For synchronization. 74 acted bool 75 ConnID uint64 76 logHook func(uint64) 77 } 78 79 // SetLogHook sets a hook for PanicOnExceed. 80 func (a *PanicOnExceed) SetLogHook(hook func(uint64)) { 81 a.logHook = hook 82 } 83 84 // CausetAction panics when memory usage exceeds memory quota. 85 func (a *PanicOnExceed) CausetAction(t *Tracker) { 86 a.mutex.Lock() 87 if a.acted { 88 a.mutex.Unlock() 89 return 90 } 91 a.acted = true 92 a.mutex.Unlock() 93 if a.logHook != nil { 94 a.logHook(a.ConnID) 95 } 96 panic(PanicMemoryExceed + fmt.Sprintf("[conn_id=%d]", a.ConnID)) 97 } 98 99 // SetFallback sets a fallback action. 100 func (a *PanicOnExceed) SetFallback(SuperCowOrNoCausetOnExceed) {} 101 102 var ( 103 errMemExceedThreshold = terror.ClassUtil.New(errno.ErrMemExceedThreshold, errno.MyALLEGROSQLErrName[errno.ErrMemExceedThreshold]) 104 ) 105 106 const ( 107 // PanicMemoryExceed represents the panic message when out of memory quota. 108 PanicMemoryExceed string = "Out Of Memory Quota!" 109 )