1 /*
2  * Copyright (c) 2021 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 #include "flow_control.h"
16 
17 #include <fstream>
18 #include <iostream>
19 #include <strstream>
20 #include <string>
21 #include <ctime>
22 #include <atomic>
23 #include <unordered_map>
24 #include <unistd.h>
25 #include <hilog/log.h>
26 #include "properties.h"
27 #include "log_timestamp.h"
28 #include "log_utils.h"
29 
30 namespace OHOS {
31 namespace HiviewDFX {
32 constexpr int FLOW_CTL_NORAML = 0;
33 constexpr int FLOW_CTL_DROPPED = -1;
34 
35 using DomainInfo = struct {
36     uint32_t quota;
37     uint32_t sumLen;
38     uint32_t dropped;
39     LogTimeStamp startTime;
40 };
41 static std::unordered_map<uint32_t, DomainInfo> g_domainMap;
42 
FlowCtrlDomain(const HilogMsg & hilogMsg)43 int FlowCtrlDomain(const HilogMsg& hilogMsg)
44 {
45     static const LogTimeStamp PERIOD(1, 0);
46     if (hilogMsg.type == LOG_APP) {
47         return FLOW_CTL_NORAML;
48     }
49     int ret = FLOW_CTL_NORAML;
50     uint32_t domainId = hilogMsg.domain;
51     auto logLen = hilogMsg.len - sizeof(HilogMsg) - 1 - 1; /* quota length exclude '\0' of tag and log content */
52     LogTimeStamp tsNow(hilogMsg.mono_sec, hilogMsg.tv_nsec);
53     auto it = g_domainMap.find(domainId);
54     if (it != g_domainMap.end()) {
55         LogTimeStamp start = it->second.startTime;
56         start += PERIOD;
57         /* in statistic period(1 second) */
58         if (tsNow > start) { /* new statistic period */
59             it->second.startTime = tsNow;
60             it->second.sumLen = logLen;
61             ret = static_cast<int>(it->second.dropped);
62             it->second.dropped = 0;
63         } else {
64             if (it->second.sumLen <= it->second.quota) { /* under quota */
65                 it->second.sumLen += logLen;
66                 ret = FLOW_CTL_NORAML;
67             } else { /* over quota */
68                 it->second.dropped++;
69                 ret = FLOW_CTL_DROPPED;
70             }
71         }
72     } else {
73         int quota = GetDomainQuota(domainId);
74         DomainInfo info{static_cast<uint32_t>(quota), logLen, 0, tsNow};
75         g_domainMap.emplace(domainId, info);
76     }
77     return ret;
78 }
79 } // namespace HiviewDFX
80 } // namespace OHOS
81