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 #include "write_controller.h"
17
18 #include <__mutex_base>
19 #include <chrono>
20 #include <cstddef>
21 #include <cstdint>
22 #include <iosfwd>
23 #include <ostream>
24 #include <sys/time.h>
25 #include <sstream>
26 #include <string>
27
28 #include "hilog/log.h"
29
30 #undef LOG_DOMAIN
31 #define LOG_DOMAIN 0xD002D08
32
33 #undef LOG_TAG
34 #define LOG_TAG "WRITE_CONTROLLER"
35
36 namespace OHOS {
37 namespace HiviewDFX {
38 namespace {
39 constexpr int SEC_TO_MILLS = 1000;
40 constexpr uint64_t PRIME = 0x100000001B3ull;
41 constexpr uint64_t BASIS = 0xCBF29CE484222325ull;
42 constexpr char CONNECTOR[] = "_";
43
GenerateHash(const std::string & info)44 uint64_t GenerateHash(const std::string& info)
45 {
46 uint64_t ret {BASIS};
47 const char* p = info.c_str();
48 size_t infoLen = info.size();
49 size_t infoLenLimit = 256;
50 size_t hashLen = (infoLen < infoLenLimit) ? infoLen : infoLenLimit;
51 size_t i = 0;
52 while (i < hashLen) {
53 ret ^= *(p + i);
54 ret *= PRIME;
55 i++;
56 }
57 return ret;
58 }
59 }
60
GetCurrentTimeMills()61 uint64_t WriteController::GetCurrentTimeMills()
62 {
63 auto now = std::chrono::system_clock::now();
64 auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
65 return millisecs.count();
66 }
67
CheckLimitWritingEvent(const ControlParam & param,const char * domain,const char * eventName,const CallerInfo & callerInfo)68 uint64_t WriteController::CheckLimitWritingEvent(const ControlParam& param, const char* domain, const char* eventName,
69 const CallerInfo& callerInfo)
70 {
71 std::lock_guard<std::mutex> lock(lmtMutex);
72 uint64_t key = ConcatenateInfoAsKey(eventName, callerInfo.func, callerInfo.line);
73 EventLimitStat stat = lruCache.Get(key);
74 uint64_t cur = callerInfo.timeStamp;
75 if (!stat.IsValid() || ((stat.begin / SEC_TO_MILLS) + param.period < (cur / SEC_TO_MILLS)) ||
76 ((stat.begin / SEC_TO_MILLS) > (cur / SEC_TO_MILLS))) {
77 stat.count = 1; // record the first event writing during one cycle
78 stat.begin = cur;
79 lruCache.Put(key, stat);
80 return cur;
81 }
82 stat.count++;
83 if (stat.count <= param.threshold) {
84 lruCache.Put(key, stat);
85 return cur;
86 }
87 lruCache.Put(key, stat);
88 HILOG_DEBUG(LOG_CORE, "{.period = %{public}zu, .threshold = %{public}zu} "
89 "[%{public}lld, %{public}lld] discard %{public}zu event(s) "
90 "with domain %{public}s and name %{public}s which wrote in function %{public}s.",
91 param.period, param.threshold, static_cast<long long>(stat.begin / SEC_TO_MILLS),
92 static_cast<long long>(cur / SEC_TO_MILLS), stat.count - param.threshold,
93 domain, eventName, callerInfo.func);
94 return INVALID_TIME_STAMP;
95 }
96
CheckLimitWritingEvent(const ControlParam & param,const char * domain,const char * eventName,const char * func,int64_t line)97 uint64_t WriteController::CheckLimitWritingEvent(const ControlParam& param, const char* domain,
98 const char* eventName, const char* func, int64_t line)
99 {
100 CallerInfo info = {
101 .func = func,
102 .line = line,
103 .timeStamp = GetCurrentTimeMills(),
104 };
105 return CheckLimitWritingEvent(param, domain, eventName, info);
106 }
107
ConcatenateInfoAsKey(const char * eventName,const char * func,int64_t line) const108 uint64_t WriteController::ConcatenateInfoAsKey(const char* eventName, const char* func, int64_t line) const
109 {
110 std::string key;
111 key.append(eventName).append(CONNECTOR).append(func).append(CONNECTOR).append(std::to_string(line));
112 return GenerateHash(key);
113 }
114 } // HiviewDFX
115 } // OHOS