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