• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 #include "sys_event_doc_reader.h"
16 
17 #include <cinttypes>
18 
19 #include "event_db_file_util.h"
20 #include "hiview_logger.h"
21 #include "securec.h"
22 #include "string_util.h"
23 #include "sys_event_query.h"
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace EventStore {
28 DEFINE_LOG_TAG("HiView-SysEventDocReader");
29 using OHOS::HiviewDFX::EventRaw::RawData;
30 namespace {
31 template<typename T>
GetNegativeNum(T num)32 int32_t GetNegativeNum(T num)
33 {
34     return static_cast<int32_t>(~(num - 1)); // 1 for binary conversion
35 }
36 
37 template<typename T>
ReadValueAndReset(std::ifstream & in,T & value)38 void ReadValueAndReset(std::ifstream& in, T& value)
39 {
40     in.read(reinterpret_cast<char*>(&value), sizeof(T));
41     in.seekg(GetNegativeNum(sizeof(T)), std::ios::cur);
42 }
43 }
44 
SysEventDocReader(const std::string & path)45 SysEventDocReader::SysEventDocReader(const std::string& path): EventDocReader(path)
46 {
47     Init(path);
48 }
49 
~SysEventDocReader()50 SysEventDocReader::~SysEventDocReader()
51 {
52     if (in_.is_open()) {
53         in_.close();
54     }
55 }
56 
Init(const std::string & path)57 void SysEventDocReader::Init(const std::string& path)
58 {
59     in_.open(path, std::ios::binary);
60 
61     // get domain, name and level from file path
62     InitEventInfo(path);
63 
64     // get file size and data format version
65     if (in_.is_open()) {
66         auto curPos = in_.tellg();
67         in_.seekg(0, std::ios::end);
68         fileSize_ = in_.tellg();
69         in_.seekg(curPos, std::ios::beg);
70 
71         dataFmtVersion_ = ContentReader::ReadFmtVersion(in_);
72     }
73 }
74 
InitEventInfo(const std::string & path)75 void SysEventDocReader::InitEventInfo(const std::string& path)
76 {
77     std::vector<std::string> dirNames;
78     StringUtil::SplitStr(path, "/", dirNames);
79     constexpr size_t domainOffset = 2;
80     if (dirNames.size() < domainOffset) {
81         HIVIEW_LOGW("invalid size=%{public}zu of dir names", dirNames.size());
82         return;
83     }
84 
85     // init domain
86     const std::string domainStr = dirNames[dirNames.size() - domainOffset];
87     if (memcpy_s(info_.domain, MAX_DOMAIN_LEN, domainStr.c_str(), domainStr.length()) != EOK) {
88         HIVIEW_LOGE("failed to copy domain to EventInfo");
89         return;
90     }
91     std::string file = dirNames.back();
92     SplitedEventInfo eventInfo;
93     if (!EventDbFileUtil::ParseEventInfoFromDbFileName(file, eventInfo, NAME_ONLY | LEVEL_ONLY)) {
94         HIVIEW_LOGW("failed to parse event info from %{public}s", file.c_str());
95         return;
96     }
97 
98     // init name
99     if (memcpy_s(info_.name, MAX_EVENT_NAME_LEN, eventInfo.name.c_str(), eventInfo.name.length()) != EOK) {
100         HIVIEW_LOGE("failed to copy name to EventInfo");
101         return;
102     }
103 
104     // init level
105     info_.level = eventInfo.level;
106 }
107 
Read(const DocQuery & query,EntryQueue & entries,int & num)108 int SysEventDocReader::Read(const DocQuery& query, EntryQueue& entries, int& num)
109 {
110     auto saveFunc = [this, &query, &entries, &num](uint8_t* content, uint32_t& contentSize) {
111         if (content == nullptr) {
112             return false;
113         }
114         TryToAddEntry(content, contentSize, query, entries, num);
115         return true;
116     };
117     return Read(saveFunc);
118 }
119 
Read(ReadCallback callback)120 int SysEventDocReader::Read(ReadCallback callback)
121 {
122     // read the header
123     DocHeader header;
124     if (auto ret = ReadHeader(header); ret != DOC_STORE_SUCCESS) {
125         return ret;
126     }
127 
128     if (!IsValidHeader(header)) {
129         return DOC_STORE_ERROR_INVALID;
130     }
131 
132     // set event tag if have
133     if (info_.tag.empty() && strlen(header.tag) != 0) {
134         info_.tag = header.tag;
135     }
136 
137     // set page size
138     pageSize_ = header.pageSize * NUM_OF_BYTES_IN_KB;
139 
140     // read the events
141     if (pageSize_ == 0) {
142         uint8_t* content = nullptr;
143         uint32_t contentSize = 0;
144         uint32_t pageIndex = 0;
145         if (auto ret = ReadContent(&content, contentSize, pageIndex); ret != DOC_STORE_SUCCESS) {
146             return ret;
147         }
148         callback(content, contentSize);
149         delete[] content;
150         return DOC_STORE_SUCCESS;
151     }
152     return ReadPages(callback);
153 }
154 
ReadHeader(DocHeader & header)155 int SysEventDocReader::ReadHeader(DocHeader& header)
156 {
157     auto reader = ContentReaderFactory::GetInstance().Get(dataFmtVersion_);
158     if (reader == nullptr) {
159         HIVIEW_LOGE("reader is nullptr, version:%{public}d", dataFmtVersion_);
160         return DOC_STORE_ERROR_IO;
161     }
162     return reader->ReadDocDetails(in_, header, docHeaderSize_, headExtra_);
163 }
164 
ReadHeader(DocHeader & header,HeadExtraInfo & headExtra)165 int SysEventDocReader::ReadHeader(DocHeader& header, HeadExtraInfo& headExtra)
166 {
167     ReadHeader(header);
168     headExtra = headExtra_;
169     return DOC_STORE_SUCCESS;
170 }
171 
ReadPages(ReadCallback callback)172 int SysEventDocReader::ReadPages(ReadCallback callback)
173 {
174     uint32_t pageIndex = 0;
175     while (!HasReadFileEnd()) {
176         uint8_t* content = nullptr;
177         uint32_t contentSize = 0;
178         if (ReadContent(&content, contentSize, pageIndex) != DOC_STORE_SUCCESS) {
179             pageIndex++;
180             if (SeekgPage(pageIndex) != DOC_STORE_SUCCESS) {
181                 HIVIEW_LOGD("end to seekg the next page index=%{public}" PRIu32 ", file=%{public}s",
182                     pageIndex, docPath_.c_str());
183                 break;
184             }
185             HIVIEW_LOGD("read the next page index=%{public}" PRIu32 ", file=%{public}s", pageIndex, docPath_.c_str());
186             continue;
187         }
188         callback(content, contentSize);
189         delete[] content;
190     }
191     return DOC_STORE_SUCCESS;
192 }
193 
HasReadFileEnd()194 bool SysEventDocReader::HasReadFileEnd()
195 {
196     if (!in_.is_open()) {
197         return true;
198     }
199     return (static_cast<int>(in_.tellg()) < 0) || in_.eof();
200 }
201 
HasReadPageEnd(uint32_t pageIndex)202 bool SysEventDocReader::HasReadPageEnd(uint32_t pageIndex)
203 {
204     if (HasReadFileEnd()) {
205         return true;
206     }
207     uint32_t curPos = static_cast<uint32_t>(in_.tellg());
208     if (curPos <= docHeaderSize_) {
209         return false;
210     }
211     if (curPos == docHeaderSize_ + pageSize_ * (pageIndex + 1)) {
212         /* if no byte of current page is filled with '\0' charactor,
213          * when position is at the end of current page,
214          * we should check whether page is end by page index increment.
215          */
216         return true;
217     }
218     return ((curPos - docHeaderSize_) % pageSize_ + HIVIEW_BLOCK_SIZE) >= pageSize_;
219 }
220 
ReadContent(uint8_t ** content,uint32_t & contentSize,uint32_t pageIndex)221 int SysEventDocReader::ReadContent(uint8_t** content, uint32_t& contentSize, uint32_t pageIndex)
222 {
223     if (HasReadPageEnd(pageIndex)) {
224         HIVIEW_LOGD("end to read the page, file=%{public}s", docPath_.c_str());
225         return DOC_STORE_READ_EMPTY;
226     }
227     ReadValueAndReset(in_, contentSize);
228     constexpr uint32_t minContentSize = HIVIEW_BLOCK_SIZE + sizeof(ContentHeader) + CRC_SIZE;
229     if (contentSize < minContentSize) {
230         HIVIEW_LOGD("invalid content size=%{public}u, file=%{public}s", contentSize, docPath_.c_str());
231         return DOC_STORE_READ_EMPTY;
232     }
233     if (contentSize > MAX_NEW_SIZE) {
234         HIVIEW_LOGE("invalid content size=%{public}u", contentSize);
235         return DOC_STORE_ERROR_MEMORY;
236     }
237     *content = new(std::nothrow) uint8_t[contentSize];
238     if (*content == nullptr) {
239         HIVIEW_LOGE("failed to new memory for content, size=%{public}u", contentSize);
240         return DOC_STORE_ERROR_MEMORY;
241     }
242     in_.read(reinterpret_cast<char*>(*content), contentSize);
243     return DOC_STORE_SUCCESS;
244 }
245 
ReadFileSize()246 int SysEventDocReader::ReadFileSize()
247 {
248     return fileSize_;
249 }
250 
ReadPageSize(uint32_t & pageSize)251 int SysEventDocReader::ReadPageSize(uint32_t& pageSize)
252 {
253     DocHeader header;
254     if (int ret = ReadHeader(header); ret != DOC_STORE_SUCCESS) {
255         return ret;
256     }
257     pageSize = header.pageSize * NUM_OF_BYTES_IN_KB;
258     return DOC_STORE_SUCCESS;
259 }
260 
IsValidHeader(const DocHeader & header)261 bool SysEventDocReader::IsValidHeader(const DocHeader& header)
262 {
263     auto reader = ContentReaderFactory::GetInstance().Get(dataFmtVersion_);
264     if (reader == nullptr) {
265         HIVIEW_LOGE("reader nullptr, version:%{public}d", dataFmtVersion_);
266         return false;
267     }
268     if (!reader->IsValidMagicNum(header.magicNum)) {
269         HIVIEW_LOGE("invalid magic number of file=%{public}s", docPath_.c_str());
270         return false;
271     }
272     return true;
273 }
274 
SeekgPage(uint32_t pageIndex)275 int SysEventDocReader::SeekgPage(uint32_t pageIndex)
276 {
277     if (HasReadFileEnd()) {
278         return DOC_STORE_ERROR_IO;
279     }
280     auto seekSize = docHeaderSize_ + pageSize_ * pageIndex;
281     if (static_cast<int>(seekSize) < ReadFileSize()) {
282         in_.seekg(seekSize, std::ios::beg);
283         return DOC_STORE_SUCCESS;
284     }
285     in_.setstate(std::ios::eofbit);
286     return DOC_STORE_ERROR_IO;
287 }
288 
BuildRawData(uint8_t * content,uint32_t contentSize)289 std::shared_ptr<RawData> SysEventDocReader::BuildRawData(uint8_t* content, uint32_t contentSize)
290 {
291     auto reader = ContentReaderFactory::GetInstance().Get(dataFmtVersion_);
292     if (reader == nullptr) {
293         HIVIEW_LOGE("reader nullptr, version:%{public}d", dataFmtVersion_);
294         return nullptr;
295     }
296     return reader->ReadRawData(info_, content, contentSize);
297 }
298 
TryToAddEntry(uint8_t * content,uint32_t contentSize,const DocQuery & query,EntryQueue & entries,int & num)299 void SysEventDocReader::TryToAddEntry(uint8_t* content, uint32_t contentSize, const DocQuery& query,
300     EntryQueue& entries, int& num)
301 {
302     if (!CheckEventInfo(content)) {
303         return;
304     }
305 
306     // check inner condition
307     if (!query.IsContainInnerConds(content)) {
308         return;
309     }
310     // build raw data
311     auto rawData = BuildRawData(content, contentSize);
312     if (rawData == nullptr) {
313         return;
314     }
315     // check extra condition
316     if (!query.IsContainExtraConds(rawData->GetData(), rawData->GetDataLength())) {
317         return;
318     }
319     // add to entry queue
320     num++;
321     entries.emplace(info_.seq, info_.timestamp, rawData, headExtra_.sysVersion, headExtra_.patchVersion);
322 }
323 
CheckEventInfo(uint8_t * content)324 bool SysEventDocReader::CheckEventInfo(uint8_t* content)
325 {
326     if (strlen(info_.domain) == 0 || strlen(info_.name) == 0 || info_.level.empty()) {
327         HIVIEW_LOGE("domain=%{public}s or name=%{public}s or level=%{public}s is empty",
328             info_.domain, info_.name, info_.level.c_str());
329         return false;
330     }
331 
332     int64_t seq = *(reinterpret_cast<int64_t*>(content + HIVIEW_BLOCK_SIZE));
333     if (seq < 0) {
334         HIVIEW_LOGE("event seq is invalid, seq=%{public}" PRId64, seq);
335         return false;
336     }
337     info_.seq = seq;
338 
339     int64_t timestamp = *(reinterpret_cast<int64_t*>(content + HIVIEW_BLOCK_SIZE + SEQ_SIZE));
340     if (timestamp < 0) {
341         HIVIEW_LOGE("event seq is invalid, timestamp=%{public}" PRId64, timestamp);
342         return false;
343     }
344     info_.timestamp = timestamp;
345 
346     return true;
347 }
348 
ReadMaxEventSequence()349 int64_t SysEventDocReader::ReadMaxEventSequence()
350 {
351     int64_t maxSeq = 0;
352     auto callback = [&maxSeq] (uint8_t* content, uint32_t& contentSize) {
353         if (content == nullptr || contentSize < HIVIEW_BLOCK_SIZE + sizeof(int64_t)) {
354             HIVIEW_LOGE("invalid event, content size is %{public}" PRIu32 "", contentSize);
355             return false;
356         }
357         int64_t seq = *(reinterpret_cast<int64_t*>(content + HIVIEW_BLOCK_SIZE));
358         if (maxSeq < seq) {
359             maxSeq = seq;
360         }
361         return true;
362     };
363     (void)Read(callback);
364     return maxSeq;
365 }
366 } // EventStore
367 } // HiviewDFX
368 } // OHOS
369