• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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