1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "daily_controller.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include <cmath> 18020a203aSopenharmony_ci 19020a203aSopenharmony_ci#include "hiview_logger.h" 20020a203aSopenharmony_ci#include "time_util.h" 21020a203aSopenharmony_ci 22020a203aSopenharmony_cinamespace OHOS { 23020a203aSopenharmony_cinamespace HiviewDFX { 24020a203aSopenharmony_ciDEFINE_LOG_TAG("DailyController"); 25020a203aSopenharmony_cinamespace { 26020a203aSopenharmony_ciconstexpr int32_t COUNT_OF_INIT = 1; 27020a203aSopenharmony_ci} 28020a203aSopenharmony_ci 29020a203aSopenharmony_ciDailyController::DailyController(const std::string& workPath, const std::string& configPath) 30020a203aSopenharmony_ci{ 31020a203aSopenharmony_ci dbHelper_ = std::make_unique<DailyDbHelper>(workPath); 32020a203aSopenharmony_ci config_ = std::make_unique<DailyConfig>(configPath); 33020a203aSopenharmony_ci} 34020a203aSopenharmony_ci 35020a203aSopenharmony_cibool DailyController::CheckThreshold(std::shared_ptr<SysEvent> event) 36020a203aSopenharmony_ci{ 37020a203aSopenharmony_ci if (event == nullptr) { 38020a203aSopenharmony_ci HIVIEW_LOGW("event is null"); 39020a203aSopenharmony_ci return false; 40020a203aSopenharmony_ci } 41020a203aSopenharmony_ci 42020a203aSopenharmony_ci // try to update cache to db and report db before checking 43020a203aSopenharmony_ci int64_t nowTime = TimeUtil::GetSeconds(); 44020a203aSopenharmony_ci TryToUpdateCacheToDb(nowTime); 45020a203aSopenharmony_ci TryToReportDb(nowTime); 46020a203aSopenharmony_ci 47020a203aSopenharmony_ci // check the threshold of event 48020a203aSopenharmony_ci auto cacheKey = std::make_pair(event->domain_, event->eventName_); 49020a203aSopenharmony_ci int32_t threshold = GetThreshold(cacheKey, event->eventType_); 50020a203aSopenharmony_ci int32_t count = GetCount(cacheKey) + 1; 51020a203aSopenharmony_ci 52020a203aSopenharmony_ci // update cache and db after checking 53020a203aSopenharmony_ci UpdateCacheAndDb(cacheKey, threshold, count); 54020a203aSopenharmony_ci return config_->IsValid() ? (count <= threshold) : true; 55020a203aSopenharmony_ci} 56020a203aSopenharmony_ci 57020a203aSopenharmony_civoid DailyController::TryToUpdateCacheToDb(int64_t nowTime) 58020a203aSopenharmony_ci{ 59020a203aSopenharmony_ci if (CheckTimeOfCache(nowTime) || CheckSizeOfCache()) { 60020a203aSopenharmony_ci UpdateCacheToDb(); 61020a203aSopenharmony_ci } 62020a203aSopenharmony_ci} 63020a203aSopenharmony_ci 64020a203aSopenharmony_cibool DailyController::CheckTimeOfCache(int64_t nowTime) 65020a203aSopenharmony_ci{ 66020a203aSopenharmony_ci static int64_t lastUpdateTime = 0; 67020a203aSopenharmony_ci if (lastUpdateTime == 0) { 68020a203aSopenharmony_ci lastUpdateTime = TimeUtil::GetSeconds(); 69020a203aSopenharmony_ci return false; 70020a203aSopenharmony_ci } 71020a203aSopenharmony_ci 72020a203aSopenharmony_ci constexpr int64_t updateInterval = 600; // 10min 73020a203aSopenharmony_ci if (std::abs(nowTime - lastUpdateTime) <= updateInterval) { 74020a203aSopenharmony_ci return false; 75020a203aSopenharmony_ci } 76020a203aSopenharmony_ci lastUpdateTime = nowTime; 77020a203aSopenharmony_ci return true; 78020a203aSopenharmony_ci} 79020a203aSopenharmony_ci 80020a203aSopenharmony_cibool DailyController::CheckSizeOfCache() 81020a203aSopenharmony_ci{ 82020a203aSopenharmony_ci constexpr size_t maxSizeOfCache = 1000; 83020a203aSopenharmony_ci return cache_.size() > maxSizeOfCache; 84020a203aSopenharmony_ci} 85020a203aSopenharmony_ci 86020a203aSopenharmony_civoid DailyController::UpdateCacheToDb() 87020a203aSopenharmony_ci{ 88020a203aSopenharmony_ci HIVIEW_LOGI("start to update cache to db, size=%{public}zu", cache_.size()); 89020a203aSopenharmony_ci for (const auto& [key, value] : cache_) { 90020a203aSopenharmony_ci // means that the record has been inserted and does not need to be updated 91020a203aSopenharmony_ci if (value.count == COUNT_OF_INIT) { 92020a203aSopenharmony_ci continue; 93020a203aSopenharmony_ci } 94020a203aSopenharmony_ci 95020a203aSopenharmony_ci DailyDbHelper::EventInfo eventInfo = { 96020a203aSopenharmony_ci .domain = key.first, 97020a203aSopenharmony_ci .name = key.second, 98020a203aSopenharmony_ci .count = value.count, 99020a203aSopenharmony_ci .exceedTime = value.exceedTime, 100020a203aSopenharmony_ci }; 101020a203aSopenharmony_ci if (dbHelper_->UpdateEventInfo(eventInfo) < 0) { 102020a203aSopenharmony_ci HIVIEW_LOGW("failed to update, domain=%{public}s, name=%{public}s", 103020a203aSopenharmony_ci key.first.c_str(), key.second.c_str()); 104020a203aSopenharmony_ci } 105020a203aSopenharmony_ci } 106020a203aSopenharmony_ci cache_.clear(); 107020a203aSopenharmony_ci} 108020a203aSopenharmony_ci 109020a203aSopenharmony_civoid DailyController::TryToReportDb(int64_t nowTime) 110020a203aSopenharmony_ci{ 111020a203aSopenharmony_ci if (dbHelper_->NeedReport(nowTime)) { 112020a203aSopenharmony_ci UpdateCacheToDb(); 113020a203aSopenharmony_ci dbHelper_->Report(); 114020a203aSopenharmony_ci } 115020a203aSopenharmony_ci} 116020a203aSopenharmony_ci 117020a203aSopenharmony_ciint32_t DailyController::GetThreshold(const CacheKey& cachekey, int32_t type) 118020a203aSopenharmony_ci{ 119020a203aSopenharmony_ci if (cache_.find(cachekey) != cache_.end()) { 120020a203aSopenharmony_ci return cache_[cachekey].threshold; 121020a203aSopenharmony_ci } 122020a203aSopenharmony_ci int32_t threshold = config_->GetThreshold(cachekey.first, cachekey.second, type); 123020a203aSopenharmony_ci if (threshold < 0) { 124020a203aSopenharmony_ci HIVIEW_LOGW("failed to get threshold from config, threshold=%{public}d", threshold); 125020a203aSopenharmony_ci return 0; 126020a203aSopenharmony_ci } 127020a203aSopenharmony_ci return threshold; 128020a203aSopenharmony_ci} 129020a203aSopenharmony_ci 130020a203aSopenharmony_ciint32_t DailyController::GetCount(const CacheKey& cachekey) 131020a203aSopenharmony_ci{ 132020a203aSopenharmony_ci if (cache_.find(cachekey) != cache_.end()) { 133020a203aSopenharmony_ci return cache_[cachekey].count; 134020a203aSopenharmony_ci } 135020a203aSopenharmony_ci 136020a203aSopenharmony_ci DailyDbHelper::EventInfo eventInfo = { 137020a203aSopenharmony_ci .domain = cachekey.first, 138020a203aSopenharmony_ci .name = cachekey.second, 139020a203aSopenharmony_ci }; 140020a203aSopenharmony_ci if (dbHelper_->QueryEventInfo(eventInfo) < 0) { 141020a203aSopenharmony_ci HIVIEW_LOGW("failed to query event info from db, count=%{public}d", eventInfo.count); 142020a203aSopenharmony_ci return 0; 143020a203aSopenharmony_ci } 144020a203aSopenharmony_ci return eventInfo.count; 145020a203aSopenharmony_ci} 146020a203aSopenharmony_ci 147020a203aSopenharmony_civoid DailyController::UpdateCacheAndDb(const CacheKey& cachekey, int32_t threshold, int32_t count) 148020a203aSopenharmony_ci{ 149020a203aSopenharmony_ci // check the first time the event crosses the threshold 150020a203aSopenharmony_ci int64_t exceedTime = 0; 151020a203aSopenharmony_ci if (count == (threshold + 1)) { 152020a203aSopenharmony_ci exceedTime = TimeUtil::GetSeconds(); 153020a203aSopenharmony_ci HIVIEW_LOGI("event first exceeds threshold, domain=%{public}s, name=%{public}s", 154020a203aSopenharmony_ci cachekey.first.c_str(), cachekey.second.c_str()); 155020a203aSopenharmony_ci } 156020a203aSopenharmony_ci 157020a203aSopenharmony_ci UpdateCache(cachekey, threshold, count, exceedTime); 158020a203aSopenharmony_ci UpdateDb(cachekey, count, exceedTime); 159020a203aSopenharmony_ci} 160020a203aSopenharmony_ci 161020a203aSopenharmony_civoid DailyController::UpdateCache(const CacheKey& cachekey, int32_t threshold, int32_t count, int64_t exceedTime) 162020a203aSopenharmony_ci{ 163020a203aSopenharmony_ci if (cache_.find(cachekey) == cache_.end()) { 164020a203aSopenharmony_ci cache_[cachekey] = { 165020a203aSopenharmony_ci .threshold = threshold, 166020a203aSopenharmony_ci .count = count, 167020a203aSopenharmony_ci .exceedTime = exceedTime, 168020a203aSopenharmony_ci }; 169020a203aSopenharmony_ci return; 170020a203aSopenharmony_ci } 171020a203aSopenharmony_ci 172020a203aSopenharmony_ci cache_[cachekey].count = count; 173020a203aSopenharmony_ci if (exceedTime != 0) { 174020a203aSopenharmony_ci cache_[cachekey].exceedTime = exceedTime; 175020a203aSopenharmony_ci } 176020a203aSopenharmony_ci} 177020a203aSopenharmony_ci 178020a203aSopenharmony_civoid DailyController::UpdateDb(const CacheKey& cachekey, int32_t count, int64_t exceedTime) 179020a203aSopenharmony_ci{ 180020a203aSopenharmony_ci // the record does not exist in the db, need to init the record 181020a203aSopenharmony_ci if (count == COUNT_OF_INIT) { 182020a203aSopenharmony_ci DailyDbHelper::EventInfo eventInfo = { 183020a203aSopenharmony_ci .domain = cachekey.first, 184020a203aSopenharmony_ci .name = cachekey.second, 185020a203aSopenharmony_ci .count = count, 186020a203aSopenharmony_ci .exceedTime = exceedTime, 187020a203aSopenharmony_ci }; 188020a203aSopenharmony_ci if (dbHelper_->InsertEventInfo(eventInfo) < 0) { 189020a203aSopenharmony_ci HIVIEW_LOGW("failed to insert, domain=%{public}s, name=%{public}s", 190020a203aSopenharmony_ci eventInfo.domain.c_str(), eventInfo.name.c_str()); 191020a203aSopenharmony_ci } 192020a203aSopenharmony_ci } 193020a203aSopenharmony_ci} 194020a203aSopenharmony_ci} // namespace HiviewDFX 195020a203aSopenharmony_ci} // namespace OHOS 196