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
30namespace OHOS {
31namespace HiviewDFX {
32constexpr int FLOW_CTL_NORAML = 0;
33constexpr int FLOW_CTL_DROPPED = -1;
34
35using DomainInfo = struct {
36    uint32_t quota;
37    uint32_t sumLen;
38    uint32_t dropped;
39    LogTimeStamp startTime;
40};
41static std::unordered_map<uint32_t, DomainInfo> g_domainMap;
42
43int 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