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 HeadExtraInfo headExtra;
73 reader.ReadHeader(header, headExtra);
74 headerSize_ = header.blockSize + sizeof(header.magicNum); // for GetCurrPageRemainSize
75 if (header.version != EventStore::EVENT_DATA_FORMATE_VERSION::CURRENT ||
76 headExtra.sysVersion != Parameter::GetSysVersionStr() ||
77 headExtra.patchVersion != Parameter::GetPatchVersionStr()) {
78 return DOC_STORE_NEW_FILE;
79 }
80
81 // if file is not empty, read the file header for writing
82 uint32_t pageSize = 0;
83 if (int ret = reader.ReadPageSize(pageSize); ret != DOC_STORE_SUCCESS) {
84 HIVIEW_LOGE("failed to get pageSize from the file=%{public}s", docPath_.c_str());
85 return ret;
86 }
87
88 // if the current file is full, need to create a new file
89 if (pageSize == 0 || pageSize < contentSize) {
90 HIVIEW_LOGD("the current page is full, page=%{public}u, content=%{public}u", pageSize, contentSize);
91 return DOC_STORE_NEW_FILE;
92 }
93
94 // if the current page is full, need to add zero
95 if (auto remainSize = GetCurrPageRemainSize(fileSize, pageSize); remainSize < contentSize) {
96 if (int ret = FillCurrPageWithZero(remainSize); ret != DOC_STORE_SUCCESS) {
97 return ret;
98 }
99 }
100 return WriteContent(sysEvent, contentSize);
101 }
102
GetCurrPageRemainSize(int fileSize,uint32_t pageSize)103 uint32_t SysEventDocWriter::GetCurrPageRemainSize(int fileSize, uint32_t pageSize)
104 {
105 return (pageSize - ((static_cast<uint32_t>(fileSize) - headerSize_) % pageSize));
106 }
107
FillCurrPageWithZero(uint32_t remainSize)108 int SysEventDocWriter::FillCurrPageWithZero(uint32_t remainSize)
109 {
110 if (remainSize == 0) {
111 return DOC_STORE_SUCCESS;
112 }
113 if (remainSize > MAX_NEW_SIZE) {
114 HIVIEW_LOGE("invalid new size=%{public}u", remainSize);
115 return DOC_STORE_ERROR_MEMORY;
116 }
117 uint8_t* fillData = new(std::nothrow) uint8_t[remainSize]{ 0x0 };
118 if (fillData == nullptr) {
119 HIVIEW_LOGE("failed to new memory for fillData, size=%{public}u", remainSize);
120 return DOC_STORE_ERROR_MEMORY;
121 }
122 out_.write(reinterpret_cast<char*>(fillData), remainSize);
123 delete[] fillData;
124 return DOC_STORE_SUCCESS;
125 }
126
GetContentSize(const std::shared_ptr<SysEvent> & sysEvent,uint32_t & contentSize)127 int SysEventDocWriter::GetContentSize(const std::shared_ptr<SysEvent>& sysEvent, uint32_t& contentSize)
128 {
129 uint8_t* rawData = sysEvent->AsRawData();
130 if (rawData == nullptr) {
131 HIVIEW_LOGE("The raw data of event is null");
132 return DOC_STORE_ERROR_NULL;
133 }
134 uint32_t dataSize = *(reinterpret_cast<uint32_t*>(rawData));
135 if (dataSize < RAW_DATA_OFFSET || dataSize > MAX_NEW_SIZE) {
136 HIVIEW_LOGE("The length=%{public}u of raw data is invalid", dataSize);
137 return DOC_STORE_ERROR_INVALID;
138 }
139 contentSize = dataSize - RAW_DATA_OFFSET + BLOCK_SIZE + SEQ_SIZE + CRC_SIZE;
140 return DOC_STORE_SUCCESS;
141 }
142
WriteHeader(const std::shared_ptr<SysEvent> & sysEvent,uint32_t contentSize)143 int SysEventDocWriter::WriteHeader(const std::shared_ptr<SysEvent>& sysEvent, uint32_t contentSize)
144 {
145 uint32_t pageSize = EventStoreConfig::GetInstance().GetPageSize(sysEvent->eventType_);
146 if (pageSize == 0) {
147 HIVIEW_LOGE("failed to get page size");
148 return DOC_STORE_ERROR_IO;
149 }
150 pageSize = contentSize > (pageSize * NUM_OF_BYTES_IN_KB) ? 0 : pageSize;
151
152 DocHeader header = {
153 .magicNum = MAGIC_NUM,
154 .pageSize = pageSize,
155 .version = EventStore::EVENT_DATA_FORMATE_VERSION::CURRENT,
156 };
157 if (!sysEvent->GetTag().empty() && strcpy_s(header.tag, MAX_TAG_LEN, sysEvent->GetTag().c_str()) != EOK) {
158 HIVIEW_LOGW("failed to copy tag to event, tag=%{public}s", sysEvent->GetTag().c_str());
159 }
160 auto sysVersion = Parameter::GetSysVersionStr();
161 uint32_t sysVersionSize = sysVersion.length() + 1; // reserve one byte for '\0'
162 auto patchVersion = Parameter::GetPatchVersionStr();
163 uint32_t patchVersionSize = patchVersion.length() + 1; // reserve one byte for '\0'
164 header.blockSize = sizeof(DocHeader) - sizeof(header.magicNum)
165 + sizeof(sysVersionSize) + sysVersionSize
166 + sizeof(patchVersionSize) + patchVersionSize;
167 headerSize_ = header.blockSize + sizeof(header.magicNum);
168 out_.write(reinterpret_cast<char*>(&header), sizeof(DocHeader));
169 out_.write(reinterpret_cast<char*>(&sysVersionSize), sizeof(uint32_t)); // append size of system version string
170 out_.write(sysVersion.c_str(), sysVersionSize); // append system version
171 out_.write(reinterpret_cast<char*>(&patchVersionSize), sizeof(uint32_t)); // append size of patch version string
172 out_.write(patchVersion.c_str(), patchVersionSize); // append patch version
173 return DOC_STORE_SUCCESS;
174 }
175
WriteContent(const std::shared_ptr<SysEvent> & sysEvent,uint32_t contentSize)176 int SysEventDocWriter::WriteContent(const std::shared_ptr<SysEvent>& sysEvent, uint32_t contentSize)
177 {
178 // move to the end
179 out_.seekp(0, std::ios::end);
180
181 // content.blockSize
182 out_.write(reinterpret_cast<const char*>(&contentSize), sizeof(contentSize));
183
184 // content.seq
185 const auto eventSeq = sysEvent->GetEventSeq();
186 out_.write(reinterpret_cast<const char*>(&eventSeq), sizeof(eventSeq));
187
188 // content.rawData
189 uint8_t* rawData = sysEvent->AsRawData();
190 if (rawData == nullptr) {
191 HIVIEW_LOGE("The raw data of event is null");
192 return DOC_STORE_ERROR_NULL;
193 }
194 uint32_t dataSize = *(reinterpret_cast<uint32_t*>(rawData)) - RAW_DATA_OFFSET;
195 out_.write(reinterpret_cast<const char*>(rawData + RAW_DATA_OFFSET), dataSize);
196
197 // content.crc
198 const uint32_t crcDefault = 0;
199 out_.write(reinterpret_cast<const char*>(&crcDefault), CRC_SIZE);
200
201 // flush the file
202 out_.flush();
203
204 HIVIEW_LOGD("write content size=%{public}u, seq=%{public}" PRId64 ", file=%{public}s", contentSize,
205 sysEvent->GetEventSeq(), docPath_.c_str());
206 return DOC_STORE_SUCCESS;
207 }
208 } // EventStore
209 } // HiviewDFX
210 } // OHOS
211