1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
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 "trace_file_writer.h"
16 
17 #include <cinttypes>
18 #include <fcntl.h>
19 #include <memory>
20 #include <sys/mman.h>
21 #include <sys/statvfs.h>
22 #include <unistd.h>
23 #include <cstdio>
24 
25 #include "common.h"
26 #ifdef LITE_PROTO
27 #include "common_types_lite.pb.h"
28 #else
29 #include "common_types.pb.h"
30 #endif
31 #include "logging.h"
32 
33 using CharPtr = std::unique_ptr<char>::pointer;
34 using ConstCharPtr = std::unique_ptr<const char>::pointer;
35 
36 namespace {
37 constexpr int MB_TO_BYTE = (1024 * 1024);
38 constexpr int GB_TO_BYTE = (1024 * 1024 * 1024);
39 constexpr int SPLIT_FILE_MIN_SIZE = 200;    // split file min size
40 constexpr int SPLIT_FILE_DEFAULT_NUM = 10;  // split file default num
41 constexpr size_t DEFULT_PAGES = 64 * 256; // 64M
42 const int PIECE_HEAD_LEN = 4;
43 } // namespace
44 
TraceFileWriter(const std::string& path)45 TraceFileWriter::TraceFileWriter(const std::string& path) : TraceFileWriter(path, false, 0, 0) {}
46 
TraceFileWriter(int32_t fd)47 TraceFileWriter::TraceFileWriter(int32_t fd) : fd_(fd)
48 {
49     if (write(fd_, &header_, sizeof(header_)) != sizeof(header_)) {
50         PROFILER_LOG_ERROR(LOG_CORE, "write initial header failed!, error: %s", strerror(errno));
51     }
52     (void)FlushStream();
53     fileWriteLength_ = sizeof(header_);
54     mapOffset_ = sizeof(header_);
55     messageWriteOffset_ = PIECE_HEAD_LEN;
56     pageSize_ = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
57     fileLength_ = DEFULT_PAGES * pageSize_;
58 
59     if (ftruncate(fd_, fileLength_) != 0) {
60         PROFILER_LOG_ERROR(LOG_CORE, "ftruncate file(%zu) failed, error: %s", fileLength_, strerror(errno));
61         return;
62     }
63 
64     fileMapAddr_ = mmap(nullptr, fileLength_, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd_, 0);
65     if (fileMapAddr_ == MAP_FAILED) {
66         PROFILER_LOG_ERROR(LOG_CORE, "mmap file(%d) failed, error: %s", fd_, strerror(errno));
67         return;
68     }
69 
70     writeCtx_.write = this;
71     writeCtx_.ctx.getMemory = [](RandomWriteCtx* ctx, uint32_t size, uint8_t** memory, uint32_t* offset) -> bool {
72         TraceFileWriterCtx* writeCtx = reinterpret_cast<TraceFileWriterCtx*>(ctx);
73         return writeCtx->write->GetMemory(size, memory, offset);
74     };
75     writeCtx_.ctx.seek = [](RandomWriteCtx* ctx, uint32_t offset) -> bool {
76         TraceFileWriterCtx* writeCtx = reinterpret_cast<TraceFileWriterCtx*>(ctx);
77         return writeCtx->write->Seek(offset);
78     };
79 }
80 
TraceFileWriter(const std::string& path, bool splitFile, uint32_t splitFileMaxSizeMb, uint32_t splitFileMaxNum)81 TraceFileWriter::TraceFileWriter(const std::string& path, bool splitFile, uint32_t splitFileMaxSizeMb,
82     uint32_t splitFileMaxNum) : path_(path), isSplitFile_(splitFile)
83 {
84     splitFileMaxSize_ = (splitFileMaxSizeMb < SPLIT_FILE_MIN_SIZE) ? (SPLIT_FILE_MIN_SIZE * MB_TO_BYTE) :
85         (splitFileMaxSizeMb * MB_TO_BYTE);
86     splitFileMaxNum_ = (splitFileMaxNum == 0) ? SPLIT_FILE_DEFAULT_NUM : splitFileMaxNum;
87     oldPath_ = path;
88     fileNum_ = 1;
89 
90     WriteHeader();
91     (void)FlushStream();
92 }
93 
~TraceFileWriter()94 TraceFileWriter::~TraceFileWriter()
95 {
96     (void)FlushStream();
97     if (stream_.is_open()) {
98         stream_.close();
99     }
100     if (fileMapAddr_ != MMAP_FAILED) {
101         munmap(fileMapAddr_, fileLength_);
102     }
103 }
104 
Path() const105 std::string TraceFileWriter::Path() const
106 {
107     return path_;
108 }
109 
SetPluginConfig(const void* data, size_t size)110 bool TraceFileWriter::SetPluginConfig(const void* data, size_t size)
111 {
112     if (isSplitFile_) {
113         std::vector<char> configVec;
114         auto configData = reinterpret_cast<ConstCharPtr>(data);
115         configVec.insert(configVec.end(), configData, configData + size);
116         pluginConfigsData_.push_back(std::move(configVec));
117     }
118 
119     Write(data, size);
120     return true;
121 }
122 
123 #ifdef LITE_PROTO
WriteStandalonePluginData( const std::string &pluginName, const std::string &data, const std::string &pluginVersion)124 void TraceFileWriter::WriteStandalonePluginData(
125     const std::string &pluginName, const std::string &data,
126     const std::string &pluginVersion)
127 {
128     LITE::ProfilerPluginData pluginData;
129     pluginData.set_name(pluginName);
130     pluginData.set_data(data);
131     if (!pluginVersion.empty()) {
132         pluginData.set_version(pluginVersion);
133         pluginData.set_status(0);
134 
135         struct timespec ts = { 0, 0 };
136         clock_gettime(CLOCK_REALTIME, &ts);
137         pluginData.set_tv_sec(ts.tv_sec);
138         pluginData.set_tv_nsec(ts.tv_nsec);
139         pluginData.set_clock_id(LITE::ProfilerPluginData::CLOCKID_REALTIME);
140     }
141 
142     std::vector<char> msgData(pluginData.ByteSizeLong());
143     if (pluginData.SerializeToArray(msgData.data(), msgData.size()) <= 0) {
144         PROFILER_LOG_WARN(LOG_CORE, "%s StandalonePluginData SerializeToArray failed!", pluginName.c_str());
145     }
146 
147     Write(msgData.data(), msgData.size());
148 }
149 #endif
150 
SetTimeStamp()151 void TraceFileWriter::SetTimeStamp()
152 {
153     header_.data_.boottime = headerDataTime_.boottime;
154     header_.data_.realtime = headerDataTime_.realtime;
155     header_.data_.realtimeCoarse = headerDataTime_.realtimeCoarse;
156     header_.data_.monotonic = headerDataTime_.monotonic;
157     header_.data_.monotonicCoarse = headerDataTime_.monotonicCoarse;
158     header_.data_.monotonicRaw = headerDataTime_.monotonicRaw;
159     header_.data_.durationNs = headerDataTime_.durationNs;
160 }
161 
SetTimeSource()162 void TraceFileWriter::SetTimeSource()
163 {
164     constexpr uint64_t nanoSeconds = 1000000000;
165     struct timespec ts;
166     clock_gettime(CLOCK_BOOTTIME, &ts);
167     headerDataTime_.boottime = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
168         static_cast<uint64_t>(ts.tv_nsec);
169     clock_gettime(CLOCK_REALTIME, &ts);
170     headerDataTime_.realtime = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
171         static_cast<uint64_t>(ts.tv_nsec);
172     clock_gettime(CLOCK_REALTIME_COARSE, &ts);
173     headerDataTime_.realtimeCoarse = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
174         static_cast<uint64_t>(ts.tv_nsec);
175     clock_gettime(CLOCK_MONOTONIC, &ts);
176     headerDataTime_.monotonic = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
177         static_cast<uint64_t>(ts.tv_nsec);
178     clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
179     headerDataTime_.monotonicCoarse = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
180         static_cast<uint64_t>(ts.tv_nsec);
181     clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
182     headerDataTime_.monotonicRaw = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
183         static_cast<uint64_t>(ts.tv_nsec);
184 }
185 
SetDurationTime()186 void TraceFileWriter::SetDurationTime()
187 {
188     struct timespec ts;
189     clock_gettime(CLOCK_BOOTTIME, &ts);
190     constexpr uint64_t nanoSeconds = 1000000000;
191     auto currBoottime = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + static_cast<uint64_t>(ts.tv_nsec);
192     headerDataTime_.durationNs = currBoottime - headerDataTime_.boottime;
193 }
194 
WriteHeader()195 bool TraceFileWriter::WriteHeader()
196 {
197     LogDiskUsage();
198     if (isSplitFile_) {
199         std::string timeStr = COMMON::GetTimeStr();
200         std::size_t pos = oldPath_.find_last_of('.');
201         if (pos != std::string::npos) {
202             path_ = oldPath_.substr(0, pos) + "_" + timeStr + "_" + std::to_string(fileNum_) +
203                 oldPath_.substr(pos, oldPath_.size());
204         } else {
205             path_ = oldPath_ + "_" + timeStr + "_" + std::to_string(fileNum_);
206         }
207         splitFilePaths_.push(path_);
208         DeleteOldSplitFile();
209     }
210 
211     stream_ = std::ofstream(path_, std::ios_base::out | std::ios_base::binary);
212     CHECK_TRUE(stream_.is_open(), false, "open %s failed, %d!", path_.c_str(), errno);
213 
214     // write initial header, makes file write position move forward
215     helper_ = {};
216     header_ = {};
217     stream_.write(reinterpret_cast<CharPtr>(&header_), sizeof(header_));
218     CHECK_TRUE(stream_, false, "write initial header to %s failed!", path_.c_str());
219     dataSize_ = header_.HEADER_SIZE;
220     PROFILER_LOG_INFO(LOG_CORE, "write file(%s) header end", path_.c_str());
221     return true;
222 }
223 
224 // delete first split file if split file num over max
DeleteOldSplitFile()225 void TraceFileWriter::DeleteOldSplitFile()
226 {
227     if (splitFilePaths_.size() <= splitFileMaxNum_) {
228         PROFILER_LOG_INFO(LOG_CORE, "splitFilePaths_ size %zu, no need to delete.", splitFilePaths_.size());
229         return;
230     }
231 
232     std::string splitFilePath = splitFilePaths_.front();
233     int ret = unlink(splitFilePath.c_str());
234     PROFILER_LOG_INFO(LOG_CORE, "DeleteOldSplitFile remove %s return %d. ", splitFilePath.c_str(), ret);
235     splitFilePaths_.pop();
236 }
237 
Write(const void* data, size_t size)238 long TraceFileWriter::Write(const void* data, size_t size)
239 {
240     if (isSplitFile_ && !isStop_) {
241         if (IsSplitFile(size)) {
242             return -1;
243         }
244     }
245 
246     uint32_t dataLen = size;
247     CHECK_TRUE(stream_.is_open(), 0, "binary file %s not open or open failed!", path_.c_str());
248 
249     // write 4B data length.
250     stream_.write(reinterpret_cast<CharPtr>(&dataLen), sizeof(dataLen));
251     CHECK_TRUE(stream_, 0, "binary file %s write raw buffer size failed!", path_.c_str());
252     CHECK_TRUE(helper_.AddSegment(reinterpret_cast<uint8_t*>(&dataLen), sizeof(dataLen)),
253         0, "Add payload for size %u FAILED!", dataLen);
254 
255     // write data bytes
256     stream_.write(reinterpret_cast<ConstCharPtr>(data), size);
257     CHECK_TRUE(stream_, 0, "binary file %s write raw buffer data failed!", path_.c_str());
258 
259     CHECK_TRUE(helper_.AddSegment(reinterpret_cast<uint8_t*>(const_cast<void*>(data)), size),
260         0, "Add payload for data bytes %zu FAILED!", size);
261 
262     uint64_t nbytes = sizeof(dataLen) + size;
263     writeBytes_ += nbytes;
264     ++writeCount_;
265     return nbytes;
266 }
267 
WriteStandalonePluginFile(const std::string &file, const std::string &name, const std::string &version, DataType type)268 long TraceFileWriter::WriteStandalonePluginFile(const std::string &file,
269                                                 const std::string &name,
270                                                 const std::string &version,
271                                                 DataType type)
272 {
273     CHECK_TRUE(stream_.is_open(), 0, "binary file %s not open or open failed!", path_.c_str());
274     auto retFile = COMMON::CheckNotExistsFilePath(file);
275     if (!retFile.first) {
276         PROFILER_LOG_INFO(LOG_CORE, "%s:check file path %s fail", __func__, file.c_str());
277         return 0;
278     }
279     std::ifstream fsFile {}; // read data from file
280     fsFile.open(retFile.second, std::ios_base::in | std::ios_base::binary);
281     if (!fsFile.good()) {
282         PROFILER_LOG_ERROR(LOG_CORE, "open file(%s) failed: %d", file.c_str(), fsFile.rdstate());
283         return 0;
284     }
285     TraceFileHeader header {};
286     fsFile.seekg(0, std::ios_base::end);
287     uint64_t fileSize = static_cast<uint64_t>(fsFile.tellg());
288     header.data_.length += fileSize;
289     size_t size = name.size();
290     if (size > 0) {
291         if (size > PLUGIN_MODULE_NAME_MAX) {
292             PROFILER_LOG_ERROR(LOG_CORE, "standalonePluginName(%s) size(%zu) is greater than %d!",
293                 name.c_str(), size, PLUGIN_MODULE_NAME_MAX);
294         } else if (strncpy_s(header.data_.standalonePluginName, PLUGIN_MODULE_NAME_MAX, name.c_str(), size) != EOK) {
295             PROFILER_LOG_ERROR(LOG_CORE, "strncpy_s standalonePluginName(%s) error!", name.c_str());
296         }
297     }
298     size = version.size();
299     if (size > 0) {
300         if (size > PLUGIN_MODULE_VERSION_MAX) {
301             PROFILER_LOG_ERROR(LOG_CORE, "pluginVersion(%s) size(%zu) is greater than %d!",
302                 version.c_str(), size, PLUGIN_MODULE_VERSION_MAX);
303         } else if (strncpy_s(header.data_.pluginVersion, PLUGIN_MODULE_VERSION_MAX, version.c_str(), size) != EOK) {
304             PROFILER_LOG_ERROR(LOG_CORE, "strncpy_s pluginVersion(%s) error!", version.c_str());
305         }
306     }
307     header.data_.dataType = type;
308     stream_.write(reinterpret_cast<char*>(&header), sizeof(header));
309 
310     constexpr uint64_t readBufSize = 4 * 1024 * 1024;
311     std::vector<char> readBuf(readBufSize);
312     uint64_t readSize = 0;
313     fsFile.seekg(0);
314     while ((readSize = std::min(readBufSize, fileSize)) > 0) {
315         fsFile.read(readBuf.data(), readSize);
316         stream_.write(readBuf.data(), readSize);
317 
318         fileSize -= readSize;
319         writeBytes_ += readSize;
320         ++writeCount_;
321     }
322 
323     fsFile.close();
324     return fileSize;
325 }
326 
IsSplitFile(uint32_t size)327 bool TraceFileWriter::IsSplitFile(uint32_t size)
328 {
329     dataSize_ += sizeof(uint32_t) + size;
330     if (dataSize_ >= splitFileMaxSize_) {
331         PROFILER_LOG_INFO(LOG_CORE, "need to split the file(%s), data size:%d, size: %d, splitFileMaxSize_:%d",
332             path_.c_str(), dataSize_, size, splitFileMaxSize_);
333 
334         // update old file header
335         SetDurationTime();
336         Finish();
337         if (stream_.is_open()) {
338             stream_.close();
339         }
340         fileNum_++;
341 
342         // write header of the new file
343         if (!WriteHeader()) {
344             return false;
345         }
346         SetTimeSource();
347 
348         // write the plugin config of the new file
349         for (size_t i = 0; i < pluginConfigsData_.size(); i++) {
350             Write(pluginConfigsData_[i].data(), pluginConfigsData_[i].size());
351         }
352         Flush();
353         return true;
354     }
355     return false;
356 }
357 
Write(const MessageLite& message)358 long TraceFileWriter::Write(const MessageLite& message)
359 {
360     auto size = message.ByteSizeLong();
361     if (isSplitFile_ && !isStop_) {
362         if (IsSplitFile(size)) {
363             return -1;
364         }
365     }
366 
367     // serialize message to bytes array
368     std::vector<char> msgData(size);
369     CHECK_TRUE(message.SerializeToArray(msgData.data(), msgData.size()), 0, "SerializeToArray failed!");
370 
371     return Write(msgData.data(), msgData.size());
372 }
373 
Finish()374 bool TraceFileWriter::Finish()
375 {
376     // update header info
377     helper_.Update(header_);
378     SetTimeStamp(); // add timestamp in header
379 
380     if (fd_ != -1) {
381         if (lseek(fd_, 0, SEEK_SET) == -1) {
382             return false;
383         }
384         auto ret = write(fd_, &header_, sizeof(header_));
385         CHECK_TRUE(ret == sizeof(header_), false, "write initial header failed!, error: %s", strerror(errno));
386         CHECK_TRUE(ftruncate(fd_, fileWriteLength_) == 0, false, "ftruncate(%u) failed, error: %s",
387             fileWriteLength_, strerror(errno));
388     } else {
389         long long filePos = stream_.tellp();
390         if (filePos == -1) { // -1 :file not open or error
391             return false;
392         }
393         // move write position to begin of file
394         CHECK_TRUE(stream_.is_open(), false, "binary file %s not open or open failed!", path_.c_str());
395         stream_.seekp(0);
396         CHECK_TRUE(stream_, false, "seek write position to head for %s failed!", path_.c_str());
397 
398         // write final header
399         stream_.write(reinterpret_cast<CharPtr>(&header_), sizeof(header_));
400         stream_.seekp(filePos);
401         CHECK_TRUE(stream_, false, "write final header to %s failed!", path_.c_str());
402         CHECK_TRUE(stream_.flush(), false, "binary file %s flush failed!", path_.c_str());
403         PROFILER_LOG_DEBUG(LOG_CORE, "Finish: %s, bytes: %" PRIu64 ", count: %" PRIu64, path_.c_str(), writeBytes_,
404                    writeCount_);
405     }
406     return true;
407 }
408 
Flush()409 bool TraceFileWriter::Flush()
410 {
411     return FlushStream();
412 }
413 
FlushStream()414 bool TraceFileWriter::FlushStream()
415 {
416     if (fd_ == -1) {
417         CHECK_TRUE(stream_.is_open(), false, "binary file %s not open or open failed!", path_.c_str());
418         CHECK_TRUE(stream_.flush(), false, "binary file %s flush failed!", path_.c_str());
419     }
420     PROFILER_LOG_DEBUG(LOG_CORE, "flush: %s, bytes: %" PRIu64 ", count: %" PRIu64, path_.c_str(),
421                        writeBytes_, writeCount_);
422     return true;
423 }
424 
SetStopSplitFile(bool isStop)425 void TraceFileWriter::SetStopSplitFile(bool isStop)
426 {
427     isStop_ = isStop;
428 }
429 
LogDiskUsage()430 void TraceFileWriter::LogDiskUsage()
431 {
432     std::string diskPath = "/data/local/tmp/";
433     std::string::size_type pos = oldPath_.find_last_of('/');
434     if (pos != std::string::npos) {
435         diskPath = oldPath_.substr(0, pos);
436     }
437 
438     struct statvfs diskInfo;
439     int ret = statvfs(diskPath.c_str(), &diskInfo);
440     if (ret != 0) {
441         std::string errorMsg = COMMON::GetErrorMsg();
442         PROFILER_LOG_ERROR(LOG_CORE, "LogDiskUsage() return %d, path:%s, msg:%s",
443                            ret, diskPath.c_str(), errorMsg.c_str());
444         return;
445     }
446 
447     unsigned long long freeSize = static_cast<unsigned long long>(diskInfo.f_bsize) *
448         static_cast<unsigned long long>(diskInfo.f_bfree);
449     unsigned long long totalSize = static_cast<unsigned long long>(diskInfo.f_bsize) *
450         static_cast<unsigned long long>(diskInfo.f_blocks);
451     float freePercent = 0;
452     if (totalSize != 0) {
453         freePercent = static_cast<float>(freeSize) / static_cast<float>(totalSize);
454     }
455     uint32_t freeSizeGb = freeSize / GB_TO_BYTE;
456     // 100: in terms of percentage
457     PROFILER_LOG_INFO(LOG_CORE, "LogDiskUsage() freePercent:%.1f, freeSizeGb:%u", freePercent * 100, freeSizeGb);
458 }
459 
RemapFile()460 bool TraceFileWriter::RemapFile()
461 {
462     if (munmap(fileMapAddr_, fileLength_) != 0) {
463         PROFILER_LOG_ERROR(LOG_CORE, "munmap file(%zu) failed, error: %s", fileLength_, strerror(errno));
464         return false;
465     }
466 
467     // file size increased by DEFULT_PAGES * pageSize_(64M)
468     size_t newLength = fileLength_ + DEFULT_PAGES * pageSize_;
469     if (ftruncate(fd_, newLength) != 0) {
470         PROFILER_LOG_ERROR(LOG_CORE, "ftruncate file(%zu) failed, error: %s", newLength, strerror(errno));
471         return false;
472     }
473 
474     size_t remapPos = fileWriteLength_ & ~(pageSize_ - 1);
475     fileMapAddr_ = mmap(nullptr, newLength, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_POPULATE, fd_, remapPos);
476     if (fileMapAddr_ == MAP_FAILED) {
477         PROFILER_LOG_ERROR(LOG_CORE, "remap(%zu:%zu) data file failed, error: %s", newLength, remapPos,
478                            strerror(errno));
479         return false;
480     }
481 
482     mapOffset_ = fileWriteLength_ - remapPos;
483     fileLength_ = newLength;
484     PROFILER_LOG_INFO(LOG_CORE, "remap(%zu:%zu) data file(%zu) sucess", remapPos, mapOffset_, fileLength_);
485     return true;
486 }
487 
GetMemory(uint32_t size, uint8_t** memory, uint32_t* offset)488 bool TraceFileWriter::GetMemory(uint32_t size, uint8_t** memory, uint32_t* offset)
489 {
490     if ((fileWriteLength_ + PIECE_HEAD_LEN + messageWriteOffset_ + size) > fileLength_) {
491         if (!RemapFile()) {
492             PROFILER_LOG_ERROR(LOG_CORE, "RemapFile failed!");
493             return false;
494         }
495     }
496 
497     *memory = &reinterpret_cast<uint8_t*>(fileMapAddr_)[mapOffset_ + messageWriteOffset_];
498     *offset = messageWriteOffset_;
499     return true;
500 }
501 
Seek(uint32_t offset)502 bool TraceFileWriter::Seek(uint32_t offset)
503 {
504     messageWriteOffset_ = offset;
505     return true;
506 }
507 
FinishReport(int32_t size)508 void TraceFileWriter::FinishReport(int32_t size)
509 {
510     auto realSize = PIECE_HEAD_LEN + size;
511     CHECK_TRUE(helper_.AddSegment(nullptr, realSize), NO_RETVAL, "AddSegment(%d) failed, error: %s",
512         realSize, strerror(errno));
513 
514     // write data length
515     *(reinterpret_cast<int*>((&reinterpret_cast<uint8_t*>(fileMapAddr_)[mapOffset_]))) = size;
516     mapOffset_ += static_cast<uint64_t>(realSize);
517     fileWriteLength_ += static_cast<uint64_t>(realSize);
518     writeBytes_ += static_cast<uint64_t>(realSize);
519     ++writeCount_;
520 }
521 
ResetPos()522 void TraceFileWriter::ResetPos()
523 {
524     messageWriteOffset_ = PIECE_HEAD_LEN;
525 }