• 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_writer.h"
16 
17 #include "event_store_config.h"
18 #include "hiview_logger.h"
19 #include "parameter_ex.h"
20 #include "securec.h"
21 #include "sys_event_doc_reader.h"
22 
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace EventStore {
26 DEFINE_LOG_TAG("HiView-SysEventDocWriter");
27 namespace {
28 constexpr uint32_t RAW_DATA_OFFSET = BLOCK_SIZE + MAX_DOMAIN_LEN + MAX_EVENT_NAME_LEN;
29 }
SysEventDocWriter(const std::string & path)30 SysEventDocWriter::SysEventDocWriter(const std::string& path): EventDocWriter(path)
31 {
32     out_.open(path, std::ios::binary | std::ios::app);
33 }
34 
~SysEventDocWriter()35 SysEventDocWriter::~SysEventDocWriter()
36 {
37     if (out_.is_open()) {
38         out_.close();
39     }
40 }
41 
Write(const std::shared_ptr<SysEvent> & sysEvent)42 int SysEventDocWriter::Write(const std::shared_ptr<SysEvent>& sysEvent)
43 {
44     if (sysEvent == nullptr) {
45         HIVIEW_LOGE("event is null");
46         return DOC_STORE_ERROR_NULL;
47     }
48     if (!out_.is_open()) {
49         HIVIEW_LOGE("file=%{public}s is not open", docPath_.c_str());
50         return DOC_STORE_ERROR_IO;
51     }
52     uint32_t contentSize = 0;
53     if (int ret = GetContentSize(sysEvent, contentSize); ret != DOC_STORE_SUCCESS) {
54         return ret;
55     }
56     SysEventDocReader reader(docPath_);
57     int fileSize = reader.ReadFileSize();
58     if (fileSize < 0) {
59         HIVIEW_LOGE("failed to get the size of file=%{public}s", docPath_.c_str());
60         return DOC_STORE_ERROR_IO;
61     }
62 
63     // if file is empty, write header to the file first
64     if (fileSize == 0) {
65         if (auto ret = WriteHeader(sysEvent, contentSize); ret != DOC_STORE_SUCCESS) {
66             return ret;
67         }
68         return WriteContent(sysEvent, contentSize);
69     }
70 
71     DocHeader header;
72     std::string sysVersion;
73     reader.ReadHeader(header, sysVersion);
74     headerSize_ = header.blockSize + sizeof(header.magicNum); // for GetCurrPageRemainSize
75     if (header.version != EventStore::EVENT_DATA_FORMATE_VERSION::CURRENT ||
76         sysVersion != Parameter::GetSysVersionStr()) {
77         return DOC_STORE_NEW_FILE;
78     }
79 
80     // if file is not empty, read the file header for writing
81     uint32_t pageSize = 0;
82     if (int ret = reader.ReadPageSize(pageSize); ret != DOC_STORE_SUCCESS) {
83         HIVIEW_LOGE("failed to get pageSize from the file=%{public}s", docPath_.c_str());
84         return ret;
85     }
86 
87     // if the current file is full, need to create a new file
88     if (pageSize == 0 || pageSize < contentSize) {
89         HIVIEW_LOGD("the current page is full, page=%{public}u, content=%{public}u", pageSize, contentSize);
90         return DOC_STORE_NEW_FILE;
91     }
92 
93     // if the current page is full, need to add zero
94     if (auto remainSize = GetCurrPageRemainSize(fileSize, pageSize); remainSize < contentSize) {
95         if (int ret = FillCurrPageWithZero(remainSize); ret != DOC_STORE_SUCCESS) {
96             return ret;
97         }
98     }
99     return WriteContent(sysEvent, contentSize);
100 }
101 
GetCurrPageRemainSize(int fileSize,uint32_t pageSize)102 uint32_t SysEventDocWriter::GetCurrPageRemainSize(int fileSize, uint32_t pageSize)
103 {
104     return (pageSize - ((static_cast<uint32_t>(fileSize) - headerSize_) % pageSize));
105 }
106 
FillCurrPageWithZero(uint32_t remainSize)107 int SysEventDocWriter::FillCurrPageWithZero(uint32_t remainSize)
108 {
109     if (remainSize == 0) {
110         return DOC_STORE_SUCCESS;
111     }
112     if (remainSize > MAX_NEW_SIZE) {
113         HIVIEW_LOGE("invalid new size=%{public}u", remainSize);
114         return DOC_STORE_ERROR_MEMORY;
115     }
116     uint8_t* fillData = new(std::nothrow) uint8_t[remainSize]{ 0x0 };
117     if (fillData == nullptr) {
118         HIVIEW_LOGE("failed to new memory for fillData, size=%{public}u", remainSize);
119         return DOC_STORE_ERROR_MEMORY;
120     }
121     out_.write(reinterpret_cast<char*>(fillData), remainSize);
122     delete[] fillData;
123     return DOC_STORE_SUCCESS;
124 }
125 
GetContentSize(const std::shared_ptr<SysEvent> & sysEvent,uint32_t & contentSize)126 int SysEventDocWriter::GetContentSize(const std::shared_ptr<SysEvent>& sysEvent, uint32_t& contentSize)
127 {
128     uint8_t* rawData = sysEvent->AsRawData();
129     if (rawData == nullptr) {
130         HIVIEW_LOGE("The raw data of event is null");
131         return DOC_STORE_ERROR_NULL;
132     }
133     uint32_t dataSize = *(reinterpret_cast<uint32_t*>(rawData));
134     if (dataSize < RAW_DATA_OFFSET || dataSize > MAX_NEW_SIZE) {
135         HIVIEW_LOGE("The length=%{public}u of raw data is invalid", dataSize);
136         return DOC_STORE_ERROR_INVALID;
137     }
138     contentSize = dataSize - RAW_DATA_OFFSET + BLOCK_SIZE + SEQ_SIZE + CRC_SIZE;
139     return DOC_STORE_SUCCESS;
140 }
141 
WriteHeader(const std::shared_ptr<SysEvent> & sysEvent,uint32_t contentSize)142 int SysEventDocWriter::WriteHeader(const std::shared_ptr<SysEvent>& sysEvent, uint32_t contentSize)
143 {
144     uint32_t pageSize = EventStoreConfig::GetInstance().GetPageSize(sysEvent->eventType_);
145     if (pageSize == 0) {
146         HIVIEW_LOGE("failed to get page size");
147         return DOC_STORE_ERROR_IO;
148     }
149     pageSize = contentSize > (pageSize * NUM_OF_BYTES_IN_KB) ? 0 : pageSize;
150 
151     DocHeader header = {
152         .magicNum = MAGIC_NUM,
153         .pageSize = pageSize,
154         .version = EventStore::EVENT_DATA_FORMATE_VERSION::CURRENT,
155     };
156     if (!sysEvent->GetTag().empty() && strcpy_s(header.tag, MAX_TAG_LEN, sysEvent->GetTag().c_str()) != EOK) {
157         HIVIEW_LOGW("failed to copy tag to event, tag=%{public}s", sysEvent->GetTag().c_str());
158     }
159     auto sysVersion = Parameter::GetSysVersionStr();
160     uint32_t sysVersionSize = sysVersion.length() + 1; // reserve one byte for '\0'
161     header.blockSize = sizeof(DocHeader) - sizeof(header.magicNum)
162         + sizeof(sysVersionSize) + sysVersionSize;
163     headerSize_ = header.blockSize + sizeof(header.magicNum);
164     out_.write(reinterpret_cast<char*>(&header), sizeof(DocHeader));
165     out_.write(reinterpret_cast<char*>(&sysVersionSize), sizeof(uint32_t)); // append size of system version string
166     out_.write(sysVersion.c_str(), sysVersionSize); // append system version
167     return DOC_STORE_SUCCESS;
168 }
169 
WriteContent(const std::shared_ptr<SysEvent> & sysEvent,uint32_t contentSize)170 int SysEventDocWriter::WriteContent(const std::shared_ptr<SysEvent>& sysEvent, uint32_t contentSize)
171 {
172     // move to the end
173     out_.seekp(0, std::ios::end);
174 
175     // content.blockSize
176     out_.write(reinterpret_cast<const char*>(&contentSize), sizeof(contentSize));
177 
178     // content.seq
179     const auto eventSeq = sysEvent->GetEventSeq();
180     out_.write(reinterpret_cast<const char*>(&eventSeq), sizeof(eventSeq));
181 
182     // content.rawData
183     uint8_t* rawData = sysEvent->AsRawData();
184     uint32_t dataSize = *(reinterpret_cast<uint32_t*>(rawData)) - RAW_DATA_OFFSET;
185     out_.write(reinterpret_cast<const char*>(rawData + RAW_DATA_OFFSET), dataSize);
186 
187     // content.crc
188     const uint32_t crcDefault = 0;
189     out_.write(reinterpret_cast<const char*>(&crcDefault), CRC_SIZE);
190 
191     // flush the file
192     out_.flush();
193 
194     HIVIEW_LOGD("write content size=%{public}u, seq=%{public}" PRId64 ", file=%{public}s", contentSize,
195         sysEvent->GetEventSeq(), docPath_.c_str());
196     return DOC_STORE_SUCCESS;
197 }
198 } // EventStore
199 } // HiviewDFX
200 } // OHOS
201