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 size_t DEFAULT_CACHE_CAPACITY = 30; 27 static constexpr size_t HISYSEVENT_DEFAULT_PERIOD = 5; 28 static constexpr size_t HISYSEVENT_DEFAULT_THRESHOLD = 10; 29 30 using ControlParam = struct { 31 size_t period; 32 size_t threshold; 33 }; 34 35 template<typename K, typename V> 36 class LruCache { 37 public: capacity(capacity)38 LruCache(int capacity = DEFAULT_CACHE_CAPACITY): capacity(capacity) {} 39 Get(K key)40 V Get(K key) 41 { 42 V v; 43 if (key2Index.count(key) == 0) { 44 return v; 45 } 46 Modify(key); 47 return key2Index[key].value; 48 } 49 Put(K key,V value)50 void Put(K key, V value) 51 { 52 if (key2Index.count(key) > 0) { 53 key2Index[key].value = value; 54 Modify(key); 55 return; 56 } 57 if (keyCache.size() == capacity) { 58 key2Index.erase(keyCache.back()); 59 keyCache.pop_back(); 60 } 61 keyCache.push_front(key); 62 key2Index[key] = { 63 .iter = keyCache.cbegin(), 64 .value = value 65 }; 66 } 67 68 private: 69 template<typename K_, typename V_> 70 struct CacheNode { 71 typename std::list<K_>::const_iterator iter; 72 V_ value; 73 }; 74 75 private: Modify(K key)76 void Modify(K key) 77 { 78 keyCache.splice(keyCache.begin(), keyCache, key2Index[key].iter); 79 key2Index[key].iter = keyCache.cbegin(); 80 } 81 82 private: 83 size_t capacity; 84 std::unordered_map<K, CacheNode<K, V>> key2Index; 85 std::list<K> keyCache; 86 }; 87 88 class WriteController { 89 public: 90 bool CheckLimitWritingEvent(const ControlParam& param, const char* domain, const char* eventName, 91 const char* func, int64_t line); 92 93 private: 94 struct EventLimitStat { 95 size_t count; 96 timeval begin; 97 98 public: EventLimitStatEventLimitStat99 EventLimitStat() 100 { 101 count = 0; 102 gettimeofday(&begin, nullptr); 103 } 104 105 public: IsValidEventLimitStat106 bool IsValid() 107 { 108 return count > 0; 109 } 110 }; 111 112 private: 113 std::string ConcatenateInfoAsKey(const char* eventName, const char* func, int64_t line) const; 114 115 private: 116 std::mutex lmtMutex; 117 LruCache<std::string, EventLimitStat> lruCache; 118 }; 119 } // HiviewDFX 120 } // OHOS 121 122 #endif // WRITE_CONTROLLER_H