1 /*
2 * Copyright (c) 2024 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 "sys_event_dao.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28 DEFINE_LOG_TAG("HiView-EventReadHandler");
29 namespace {
30 constexpr int QUERY_LIMIT = 1000;
31 }
32
HandleRequest(RequestPtr req)33 bool EventReadHandler::HandleRequest(RequestPtr req)
34 {
35 auto readReq = BaseRequest::DownCastTo<EventReadRequest>(req);
36 int64_t exportBeginSeq = readReq->beginSeq;
37 int64_t exportEndSeq = readReq->endSeq;
38 // split range
39 std::map<int64_t, int64_t> queryRanges;
40 while (exportBeginSeq + QUERY_LIMIT < exportEndSeq) {
41 queryRanges.emplace(exportBeginSeq, exportBeginSeq + QUERY_LIMIT);
42 exportBeginSeq += QUERY_LIMIT;
43 };
44 // query by range in order
45 queryRanges.emplace(exportBeginSeq, exportEndSeq);
46 for (const auto& queryRange : queryRanges) {
47 if (!QuerySysEventInRange(queryRange, readReq->eventList,
48 [this, &readReq] (bool isQueryCompleted) {
49 auto writeReq = std::make_shared<EventWriteRequest>(readReq->moduleName, cachedSysEvents_,
50 readReq->exportDir, isQueryCompleted, readReq->maxSize);
51 auto ret = nextHandler_->HandleRequest(writeReq);
52 cachedSysEvents_.clear();
53 return ret;
54 })) {
55 return false;
56 }
57 }
58 return true;
59 }
60
QuerySysEventInRange(const std::pair<int64_t,int64_t> & queryRange,const ExportEventList & eventList,QueryCallback queryCallback)61 bool EventReadHandler::QuerySysEventInRange(const std::pair<int64_t, int64_t>& queryRange,
62 const ExportEventList& eventList, QueryCallback queryCallback)
63 {
64 bool queryRet = true;
65 int retryCnt = 3; // retry 3 times if query failed
66 while (retryCnt > 0) {
67 if (QuerySysEvent(queryRange.first, queryRange.second, eventList, queryCallback)) {
68 break;
69 }
70 cachedSysEvents_.clear();
71 retryCnt--;
72 if (retryCnt == 0) {
73 HIVIEW_LOGE("failed to export events in range[%{public}" PRId64 ",%{public}" PRId64 ")",
74 queryRange.first, queryRange.second);
75 queryRet = false;
76 break;
77 }
78 ffrt::this_task::sleep_for(std::chrono::seconds(1)); // sleep for 1 second before retry
79 }
80 if (eventExportedListener_ != nullptr) {
81 eventExportedListener_(queryRange.first, queryRange.second);
82 }
83 return queryRet;
84 }
85
QuerySysEvent(const int64_t beginSeq,const int64_t endSeq,const ExportEventList & eventList,QueryCallback queryCallback)86 bool EventReadHandler::QuerySysEvent(const int64_t beginSeq, const int64_t endSeq, const ExportEventList& eventList,
87 QueryCallback queryCallback)
88 {
89 int64_t queryCnt = endSeq - beginSeq;
90 EventStore::Cond whereCond;
91 whereCond.And(EventStore::EventCol::SEQ, EventStore::Op::GE, beginSeq)
92 .And(EventStore::EventCol::SEQ, EventStore::Op::LT, endSeq);
93 std::shared_ptr<EventStore::SysEventQuery> query = nullptr;
94 int32_t queryRet = static_cast<int32_t>(EventStore::DbQueryStatus::SUCCEED);
95 bool isFirstPartialQuery = true;
96 auto iter = eventList.begin();
97 while (queryCnt > 0 && iter != eventList.end()) {
98 int64_t queryLimit = queryCnt < QUERY_LIMIT ? queryCnt : QUERY_LIMIT;
99 query = EventStore::SysEventDao::BuildQuery(iter->first, iter->second, 0, endSeq, beginSeq);
100 query->Where(whereCond);
101 query->Order(EventStore::EventCol::SEQ, true);
102 auto resultSet = query->Execute(queryLimit, { true, isFirstPartialQuery },
103 std::make_pair(EventStore::INNER_PROCESS_ID, ""),
104 [&queryRet] (EventStore::DbQueryStatus status) {
105 queryRet = static_cast<int32_t>(status);
106 });
107 if (queryRet != static_cast<int32_t>(EventStore::DbQueryStatus::SUCCEED)) {
108 HIVIEW_LOGW("query control works when query with domain %{public}s, query ret is %{public}d",
109 iter->first.c_str(), queryRet);
110 }
111 if (!HandleQueryResult(resultSet, queryCallback, queryLimit, queryCnt)) {
112 HIVIEW_LOGE("failed to export events with domain: %{public}s in range [%{public}"
113 PRId64 ",%{publiuc}" PRId64 ")", iter->first.c_str(), beginSeq, endSeq);
114 return false;
115 }
116 iter++;
117 isFirstPartialQuery = false;
118 }
119 return queryCallback(true);
120 }
121
HandleQueryResult(EventStore::ResultSet & resultSet,QueryCallback queryCallback,const int64_t queryLimit,int64_t & totalQueryCnt)122 bool EventReadHandler::HandleQueryResult(EventStore::ResultSet& resultSet, QueryCallback queryCallback,
123 const int64_t queryLimit, int64_t& totalQueryCnt)
124 {
125 EventStore::ResultSet::RecordIter iter;
126 while (resultSet.HasNext() && totalQueryCnt > 0) {
127 iter = resultSet.Next();
128 auto currentEventStr = iter->AsJsonStr();
129 if (currentEventStr.empty()) {
130 continue;
131 }
132 if (cachedSysEvents_.size() >= static_cast<size_t>(queryLimit) && !queryCallback(false)) {
133 HIVIEW_LOGE("failed to do query callback when handle query result");
134 return false;
135 }
136 EventVersion eventVersion {
137 .systemVersion = iter->GetSysVersion(),
138 .patchVersion = iter->GetPatchVersion()
139 };
140 auto item = std::make_shared<CachedEvent>(eventVersion, iter->domain_, iter->eventName_,
141 currentEventStr);
142 if (FocusedEventUtil::IsFocusedEvent(iter->domain_, iter->eventName_)) {
143 HIVIEW_LOGI("queried event: [%{public}s|%{public}s|%{public}" PRIu64 "]", iter->domain_.c_str(),
144 iter->eventName_.c_str(), iter->happenTime_);
145 }
146 cachedSysEvents_.emplace_back(item);
147 totalQueryCnt--;
148 }
149 return true;
150 }
151
SetEventExportedListener(EventExportedListener listener)152 void EventReadHandler::SetEventExportedListener(EventExportedListener listener)
153 {
154 eventExportedListener_ = listener;
155 }
156 } // HiviewDFX
157 } // OHOS