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