• 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 #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