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