• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "event_read_handler.h"
17 
18 #include "common_utils.h"
19 #include "event_write_handler.h"
20 #include "export_db_storage.h"
21 #include "ffrt.h"
22 #include "file_util.h"
23 #include "focused_event_util.h"
24 #include "hiview_logger.h"
25 #include "running_status_logger.h"
26 #include "sys_event_dao.h"
27 
28 namespace OHOS {
29 namespace HiviewDFX {
30 DEFINE_LOG_TAG("HiView-EventExportFlow");
31 namespace {
32 constexpr int QUERY_LIMIT = 1000;
33 constexpr size_t DEFAULT_EXPORT_INFO_CNT = 1;
34 
LogExportPeriodInfo(const std::unordered_map<std::string,ExportPeriodInfo> & periodInfos)35 void LogExportPeriodInfo(const std::unordered_map<std::string, ExportPeriodInfo>& periodInfos)
36 {
37     for (const auto& periodInfo : periodInfos) {
38         std::string logInfo;
39         logInfo.append("period=[").append(periodInfo.second.timeStamp).append("]; ");
40         logInfo.append("exported_event_num=[").append(std::to_string(periodInfo.second.exportedCnt)).append("]");
41         RunningStatusLogger::GetInstance().LogEventCountStatisticInfo(logInfo);
42     }
43 }
44 
MergeExportPeriodInfo(std::unordered_map<std::string,ExportPeriodInfo> & destPeriodInfos,const std::unordered_map<std::string,ExportPeriodInfo> & srcPeriodInfos)45 void MergeExportPeriodInfo(std::unordered_map<std::string, ExportPeriodInfo>& destPeriodInfos,
46     const std::unordered_map<std::string, ExportPeriodInfo>& srcPeriodInfos)
47 {
48     for (const auto& periodInfo : srcPeriodInfos) {
49         auto findRet = destPeriodInfos.find(periodInfo.first);
50         if (findRet == destPeriodInfos.end()) {
51             destPeriodInfos.emplace(periodInfo.first, periodInfo.second);
52             continue;
53         }
54         findRet->second.exportedCnt += periodInfo.second.exportedCnt;
55     }
56 }
57 
UpdatePeriodInfoMap(std::unordered_map<std::string,ExportPeriodInfo> & periodInfos,const EventPeriodSeqInfo & eventPeriodInfo)58 void UpdatePeriodInfoMap(std::unordered_map<std::string, ExportPeriodInfo>& periodInfos,
59     const EventPeriodSeqInfo& eventPeriodInfo)
60 {
61     auto findRet = periodInfos.find(eventPeriodInfo.timeStamp);
62     if (findRet == periodInfos.end()) {
63         periodInfos.emplace(eventPeriodInfo.timeStamp,
64             ExportPeriodInfo(eventPeriodInfo.timeStamp, DEFAULT_EXPORT_INFO_CNT));
65         return;
66     }
67     findRet->second.exportedCnt++;
68 }
69 }
70 
HandleRequest(RequestPtr req)71 bool EventReadHandler::HandleRequest(RequestPtr req)
72 {
73     req_ = BaseRequest::DownCastTo<EventReadRequest>(req);
74     int64_t exportBeginSeq = req_->beginSeq;
75     int64_t exportEndSeq = req_->endSeq;
76     // split range
77     std::map<int64_t, int64_t> queryRanges;
78     while (exportBeginSeq + QUERY_LIMIT < exportEndSeq) {
79         queryRanges.emplace(exportBeginSeq, exportBeginSeq + QUERY_LIMIT);
80         exportBeginSeq += QUERY_LIMIT;
81     };
82     // query by range in order
83     queryRanges.emplace(exportBeginSeq, exportEndSeq);
84     auto readRet = true;
85     for (const auto& queryRange : queryRanges) {
86         if (!QuerySysEventInRange(queryRange, req_->eventList,
87             [this] (bool isQueryCompleted) {
88                 auto writeReq = std::make_shared<EventWriteRequest>(req_->moduleName, cachedSysEvents_,
89                     req_->exportDir, isQueryCompleted, req_->maxSize);
90                 auto ret = nextHandler_->HandleRequest(writeReq);
91                 cachedSysEvents_.clear();
92                 return ret;
93             })) {
94             readRet = false;
95             break;
96         }
97         if (allPeriodInfoInOneQueryRange_.empty()) {
98             continue;
99         }
100         MergeExportPeriodInfo(allPeriodInfo_, allPeriodInfoInOneQueryRange_);
101     }
102     LogExportPeriodInfo(allPeriodInfo_);
103     return readRet;
104 }
105 
QuerySysEventInRange(const std::pair<int64_t,int64_t> & queryRange,const ExportEventList & eventList,QueryCallback queryCallback)106 bool EventReadHandler::QuerySysEventInRange(const std::pair<int64_t, int64_t>& queryRange,
107     const ExportEventList& eventList, QueryCallback queryCallback)
108 {
109     bool queryRet = true;
110     int retryCnt = 3; // retry 3 times if query failed
111     while (retryCnt > 0) {
112         if (QuerySysEvent(queryRange.first, queryRange.second, eventList, queryCallback)) {
113             break;
114         }
115         cachedSysEvents_.clear();
116         allPeriodInfoInOneQueryRange_.clear();
117         retryCnt--;
118         if (retryCnt == 0) {
119             HIVIEW_LOGE("failed to export events in range[%{public}" PRId64 ",%{public}" PRId64 ")",
120                 queryRange.first, queryRange.second);
121             queryRet = false;
122             break;
123         }
124         ffrt::this_task::sleep_for(std::chrono::seconds(1)); // sleep for 1 second before retry
125     }
126     if (eventExportedListener_ != nullptr) {
127         eventExportedListener_(queryRange.first, queryRange.second);
128     }
129     return queryRet;
130 }
131 
QuerySysEvent(const int64_t beginSeq,const int64_t endSeq,const ExportEventList & eventList,QueryCallback queryCallback)132 bool EventReadHandler::QuerySysEvent(const int64_t beginSeq, const int64_t endSeq, const ExportEventList& eventList,
133     QueryCallback queryCallback)
134 {
135     allPeriodInfoInOneQueryRange_.clear();
136     int64_t queryCnt = endSeq - beginSeq;
137     EventStore::Cond whereCond;
138     whereCond.And(EventStore::EventCol::SEQ, EventStore::Op::GE, beginSeq)
139         .And(EventStore::EventCol::SEQ, EventStore::Op::LT, endSeq);
140     std::shared_ptr<EventStore::SysEventQuery> query = nullptr;
141     int32_t queryRet = static_cast<int32_t>(EventStore::DbQueryStatus::SUCCEED);
142     bool isFirstPartialQuery = true;
143     auto iter = eventList.begin();
144     while (queryCnt > 0 && iter != eventList.end()) {
145         int64_t queryLimit = queryCnt < QUERY_LIMIT ? queryCnt : QUERY_LIMIT;
146         query = EventStore::SysEventDao::BuildQuery(iter->first, iter->second, 0, endSeq, beginSeq);
147         query->Where(whereCond);
148         query->Order(EventStore::EventCol::SEQ, true);
149         auto resultSet = query->Execute(queryLimit, { true, isFirstPartialQuery },
150             std::make_pair(EventStore::INNER_PROCESS_ID, ""),
151             [&queryRet] (EventStore::DbQueryStatus status) {
152                 queryRet = static_cast<int32_t>(status);
153             });
154         if (queryRet != static_cast<int32_t>(EventStore::DbQueryStatus::SUCCEED)) {
155             HIVIEW_LOGW("query control works when query with domain %{public}s, query ret is %{public}d",
156                 iter->first.c_str(), queryRet);
157         }
158         if (!HandleQueryResult(resultSet, queryCallback, queryLimit, queryCnt)) {
159             HIVIEW_LOGE("failed to export events with domain: %{public}s in range [%{public}"
160                 PRId64 ",%{publiuc}" PRId64 ")", iter->first.c_str(), beginSeq, endSeq);
161             return false;
162         }
163         iter++;
164         isFirstPartialQuery = false;
165     }
166     return queryCallback(true);
167 }
168 
HandleQueryResult(EventStore::ResultSet & resultSet,QueryCallback queryCallback,const int64_t queryLimit,int64_t & totalQueryCnt)169 bool EventReadHandler::HandleQueryResult(EventStore::ResultSet& resultSet, QueryCallback queryCallback,
170     const int64_t queryLimit, int64_t& totalQueryCnt)
171 {
172     EventStore::ResultSet::RecordIter iter;
173     while (resultSet.HasNext() && totalQueryCnt > 0) {
174         iter = resultSet.Next();
175         auto currentEventStr = iter->AsJsonStr();
176         if (currentEventStr.empty()) {
177             continue;
178         }
179         if (cachedSysEvents_.size() >= static_cast<size_t>(queryLimit) && !queryCallback(false)) {
180             HIVIEW_LOGE("failed to do query callback when handle query result");
181             return false;
182         }
183         EventVersion eventVersion {
184             .systemVersion = iter->GetSysVersion(),
185             .patchVersion = iter->GetPatchVersion()
186         };
187         if ((req_->taskType != ALL_EVENT_TASK_TYPE) && (req_->taskType != iter->GetReportInterval())) {
188             continue;
189         }
190         UpdatePeriodInfoMap(allPeriodInfoInOneQueryRange_, iter->GetEventPeriodSeqInfo());
191         auto item = std::make_shared<CachedEvent>(eventVersion, iter->domain_, iter->eventName_,
192             currentEventStr, CommonUtils::GetTransformedUid(iter->GetUid()));
193         if (FocusedEventUtil::IsFocusedEvent(iter->domain_, iter->eventName_)) {
194             HIVIEW_LOGI("queried event: [%{public}s|%{public}s|%{public}" PRIu64 "]", iter->domain_.c_str(),
195                 iter->eventName_.c_str(), iter->happenTime_);
196         }
197         cachedSysEvents_.emplace_back(item);
198         totalQueryCnt--;
199     }
200     return true;
201 }
202 
SetEventExportedListener(EventExportedListener listener)203 void EventReadHandler::SetEventExportedListener(EventExportedListener listener)
204 {
205     eventExportedListener_ = listener;
206 }
207 } // HiviewDFX
208 } // OHOS
209