1 /* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 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 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef WRITE_CONTROLLER_H 17 #define WRITE_CONTROLLER_H 18 19 #include <list> 20 #include <mutex> 21 #include <sys/time.h> 22 #include <unordered_map> 23 24 namespace OHOS { 25 namespace HiviewDFX { 26 static constexpr uint64_t INVALID_TIME_STAMP = 0; 27 static constexpr size_t DEFAULT_CACHE_CAPACITY = 30; 28 static constexpr size_t HISYSEVENT_DEFAULT_PERIOD = 5; 29 static constexpr size_t HISYSEVENT_DEFAULT_THRESHOLD = 100; 30 31 using ControlParam = struct { 32 size_t period; 33 size_t threshold; 34 }; 35 36 using CallerInfo = struct { 37 const char* func; 38 int64_t line; 39 uint64_t timeStamp; 40 }; 41 42 template<typename K, typename V, size_t capacity = DEFAULT_CACHE_CAPACITY> 43 class LruCache { 44 public: Get(K key)45 V Get(K key) 46 { 47 V v; 48 if (key2Index.count(key) == 0) { 49 return v; 50 } 51 Modify(key); 52 return key2Index[key].value; 53 } 54 Put(K key,V value)55 void Put(K key, V value) 56 { 57 if (key2Index.count(key) > 0) { 58 key2Index[key].value = value; 59 Modify(key); 60 return; 61 } 62 if (keyCache.size() == capacity) { 63 key2Index.erase(keyCache.back()); 64 keyCache.pop_back(); 65 } 66 keyCache.push_front(key); 67 key2Index[key] = { 68 .iter = keyCache.cbegin(), 69 .value = value 70 }; 71 } 72 73 private: 74 template<typename K_, typename V_> 75 struct CacheNode { 76 typename std::list<K_>::const_iterator iter; 77 V_ value; 78 }; 79 80 private: Modify(K key)81 void Modify(K key) 82 { 83 keyCache.splice(keyCache.begin(), keyCache, key2Index[key].iter); 84 key2Index[key].iter = keyCache.cbegin(); 85 } 86 87 private: 88 std::unordered_map<K, CacheNode<K, V>> key2Index; 89 std::list<K> keyCache; 90 }; 91 92 class WriteController { 93 public: 94 uint64_t GetCurrentTimeMills(); 95 uint64_t CheckLimitWritingEvent(const ControlParam& param, const char* domain, const char* eventName, 96 const CallerInfo& callerInfo); 97 uint64_t CheckLimitWritingEvent(const ControlParam& param, const char* domain, const char* eventName, 98 const char* func, int64_t line); 99 100 private: 101 struct EventLimitStat { 102 size_t count; 103 uint64_t begin; 104 105 public: EventLimitStatEventLimitStat106 EventLimitStat() 107 { 108 count = 0; 109 begin = INVALID_TIME_STAMP; 110 } 111 112 public: IsValidEventLimitStat113 bool IsValid() 114 { 115 return count > 0; 116 } 117 }; 118 119 private: 120 uint64_t ConcatenateInfoAsKey(const char* eventName, const char* func, int64_t line) const; 121 122 private: 123 std::mutex lmtMutex; 124 LruCache<uint64_t, EventLimitStat> lruCache; 125 }; 126 } // HiviewDFX 127 } // OHOS 128 129 #endif // WRITE_CONTROLLER_H