106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include "trace_file_writer.h" 1606f6ba60Sopenharmony_ci 1706f6ba60Sopenharmony_ci#include <cinttypes> 1806f6ba60Sopenharmony_ci#include <fcntl.h> 1906f6ba60Sopenharmony_ci#include <memory> 2006f6ba60Sopenharmony_ci#include <sys/mman.h> 2106f6ba60Sopenharmony_ci#include <sys/statvfs.h> 2206f6ba60Sopenharmony_ci#include <unistd.h> 2306f6ba60Sopenharmony_ci#include <cstdio> 2406f6ba60Sopenharmony_ci 2506f6ba60Sopenharmony_ci#include "common.h" 2606f6ba60Sopenharmony_ci#ifdef LITE_PROTO 2706f6ba60Sopenharmony_ci#include "common_types_lite.pb.h" 2806f6ba60Sopenharmony_ci#else 2906f6ba60Sopenharmony_ci#include "common_types.pb.h" 3006f6ba60Sopenharmony_ci#endif 3106f6ba60Sopenharmony_ci#include "logging.h" 3206f6ba60Sopenharmony_ci 3306f6ba60Sopenharmony_ciusing CharPtr = std::unique_ptr<char>::pointer; 3406f6ba60Sopenharmony_ciusing ConstCharPtr = std::unique_ptr<const char>::pointer; 3506f6ba60Sopenharmony_ci 3606f6ba60Sopenharmony_cinamespace { 3706f6ba60Sopenharmony_ciconstexpr int MB_TO_BYTE = (1024 * 1024); 3806f6ba60Sopenharmony_ciconstexpr int GB_TO_BYTE = (1024 * 1024 * 1024); 3906f6ba60Sopenharmony_ciconstexpr int SPLIT_FILE_MIN_SIZE = 200; // split file min size 4006f6ba60Sopenharmony_ciconstexpr int SPLIT_FILE_DEFAULT_NUM = 10; // split file default num 4106f6ba60Sopenharmony_ciconstexpr size_t DEFULT_PAGES = 64 * 256; // 64M 4206f6ba60Sopenharmony_ciconst int PIECE_HEAD_LEN = 4; 4306f6ba60Sopenharmony_ci} // namespace 4406f6ba60Sopenharmony_ci 4506f6ba60Sopenharmony_ciTraceFileWriter::TraceFileWriter(const std::string& path) : TraceFileWriter(path, false, 0, 0) {} 4606f6ba60Sopenharmony_ci 4706f6ba60Sopenharmony_ciTraceFileWriter::TraceFileWriter(int32_t fd) : fd_(fd) 4806f6ba60Sopenharmony_ci{ 4906f6ba60Sopenharmony_ci if (write(fd_, &header_, sizeof(header_)) != sizeof(header_)) { 5006f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "write initial header failed!, error: %s", strerror(errno)); 5106f6ba60Sopenharmony_ci } 5206f6ba60Sopenharmony_ci (void)FlushStream(); 5306f6ba60Sopenharmony_ci fileWriteLength_ = sizeof(header_); 5406f6ba60Sopenharmony_ci mapOffset_ = sizeof(header_); 5506f6ba60Sopenharmony_ci messageWriteOffset_ = PIECE_HEAD_LEN; 5606f6ba60Sopenharmony_ci pageSize_ = static_cast<size_t>(sysconf(_SC_PAGE_SIZE)); 5706f6ba60Sopenharmony_ci fileLength_ = DEFULT_PAGES * pageSize_; 5806f6ba60Sopenharmony_ci 5906f6ba60Sopenharmony_ci if (ftruncate(fd_, fileLength_) != 0) { 6006f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "ftruncate file(%zu) failed, error: %s", fileLength_, strerror(errno)); 6106f6ba60Sopenharmony_ci return; 6206f6ba60Sopenharmony_ci } 6306f6ba60Sopenharmony_ci 6406f6ba60Sopenharmony_ci fileMapAddr_ = mmap(nullptr, fileLength_, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd_, 0); 6506f6ba60Sopenharmony_ci if (fileMapAddr_ == MAP_FAILED) { 6606f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "mmap file(%d) failed, error: %s", fd_, strerror(errno)); 6706f6ba60Sopenharmony_ci return; 6806f6ba60Sopenharmony_ci } 6906f6ba60Sopenharmony_ci 7006f6ba60Sopenharmony_ci writeCtx_.write = this; 7106f6ba60Sopenharmony_ci writeCtx_.ctx.getMemory = [](RandomWriteCtx* ctx, uint32_t size, uint8_t** memory, uint32_t* offset) -> bool { 7206f6ba60Sopenharmony_ci TraceFileWriterCtx* writeCtx = reinterpret_cast<TraceFileWriterCtx*>(ctx); 7306f6ba60Sopenharmony_ci return writeCtx->write->GetMemory(size, memory, offset); 7406f6ba60Sopenharmony_ci }; 7506f6ba60Sopenharmony_ci writeCtx_.ctx.seek = [](RandomWriteCtx* ctx, uint32_t offset) -> bool { 7606f6ba60Sopenharmony_ci TraceFileWriterCtx* writeCtx = reinterpret_cast<TraceFileWriterCtx*>(ctx); 7706f6ba60Sopenharmony_ci return writeCtx->write->Seek(offset); 7806f6ba60Sopenharmony_ci }; 7906f6ba60Sopenharmony_ci} 8006f6ba60Sopenharmony_ci 8106f6ba60Sopenharmony_ciTraceFileWriter::TraceFileWriter(const std::string& path, bool splitFile, uint32_t splitFileMaxSizeMb, 8206f6ba60Sopenharmony_ci uint32_t splitFileMaxNum) : path_(path), isSplitFile_(splitFile) 8306f6ba60Sopenharmony_ci{ 8406f6ba60Sopenharmony_ci splitFileMaxSize_ = (splitFileMaxSizeMb < SPLIT_FILE_MIN_SIZE) ? (SPLIT_FILE_MIN_SIZE * MB_TO_BYTE) : 8506f6ba60Sopenharmony_ci (splitFileMaxSizeMb * MB_TO_BYTE); 8606f6ba60Sopenharmony_ci splitFileMaxNum_ = (splitFileMaxNum == 0) ? SPLIT_FILE_DEFAULT_NUM : splitFileMaxNum; 8706f6ba60Sopenharmony_ci oldPath_ = path; 8806f6ba60Sopenharmony_ci fileNum_ = 1; 8906f6ba60Sopenharmony_ci 9006f6ba60Sopenharmony_ci WriteHeader(); 9106f6ba60Sopenharmony_ci (void)FlushStream(); 9206f6ba60Sopenharmony_ci} 9306f6ba60Sopenharmony_ci 9406f6ba60Sopenharmony_ciTraceFileWriter::~TraceFileWriter() 9506f6ba60Sopenharmony_ci{ 9606f6ba60Sopenharmony_ci (void)FlushStream(); 9706f6ba60Sopenharmony_ci if (stream_.is_open()) { 9806f6ba60Sopenharmony_ci stream_.close(); 9906f6ba60Sopenharmony_ci } 10006f6ba60Sopenharmony_ci if (fileMapAddr_ != MMAP_FAILED) { 10106f6ba60Sopenharmony_ci munmap(fileMapAddr_, fileLength_); 10206f6ba60Sopenharmony_ci } 10306f6ba60Sopenharmony_ci} 10406f6ba60Sopenharmony_ci 10506f6ba60Sopenharmony_cistd::string TraceFileWriter::Path() const 10606f6ba60Sopenharmony_ci{ 10706f6ba60Sopenharmony_ci return path_; 10806f6ba60Sopenharmony_ci} 10906f6ba60Sopenharmony_ci 11006f6ba60Sopenharmony_cibool TraceFileWriter::SetPluginConfig(const void* data, size_t size) 11106f6ba60Sopenharmony_ci{ 11206f6ba60Sopenharmony_ci if (isSplitFile_) { 11306f6ba60Sopenharmony_ci std::vector<char> configVec; 11406f6ba60Sopenharmony_ci auto configData = reinterpret_cast<ConstCharPtr>(data); 11506f6ba60Sopenharmony_ci configVec.insert(configVec.end(), configData, configData + size); 11606f6ba60Sopenharmony_ci pluginConfigsData_.push_back(std::move(configVec)); 11706f6ba60Sopenharmony_ci } 11806f6ba60Sopenharmony_ci 11906f6ba60Sopenharmony_ci Write(data, size); 12006f6ba60Sopenharmony_ci return true; 12106f6ba60Sopenharmony_ci} 12206f6ba60Sopenharmony_ci 12306f6ba60Sopenharmony_ci#ifdef LITE_PROTO 12406f6ba60Sopenharmony_civoid TraceFileWriter::WriteStandalonePluginData( 12506f6ba60Sopenharmony_ci const std::string &pluginName, const std::string &data, 12606f6ba60Sopenharmony_ci const std::string &pluginVersion) 12706f6ba60Sopenharmony_ci{ 12806f6ba60Sopenharmony_ci LITE::ProfilerPluginData pluginData; 12906f6ba60Sopenharmony_ci pluginData.set_name(pluginName); 13006f6ba60Sopenharmony_ci pluginData.set_data(data); 13106f6ba60Sopenharmony_ci if (!pluginVersion.empty()) { 13206f6ba60Sopenharmony_ci pluginData.set_version(pluginVersion); 13306f6ba60Sopenharmony_ci pluginData.set_status(0); 13406f6ba60Sopenharmony_ci 13506f6ba60Sopenharmony_ci struct timespec ts = { 0, 0 }; 13606f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &ts); 13706f6ba60Sopenharmony_ci pluginData.set_tv_sec(ts.tv_sec); 13806f6ba60Sopenharmony_ci pluginData.set_tv_nsec(ts.tv_nsec); 13906f6ba60Sopenharmony_ci pluginData.set_clock_id(LITE::ProfilerPluginData::CLOCKID_REALTIME); 14006f6ba60Sopenharmony_ci } 14106f6ba60Sopenharmony_ci 14206f6ba60Sopenharmony_ci std::vector<char> msgData(pluginData.ByteSizeLong()); 14306f6ba60Sopenharmony_ci if (pluginData.SerializeToArray(msgData.data(), msgData.size()) <= 0) { 14406f6ba60Sopenharmony_ci PROFILER_LOG_WARN(LOG_CORE, "%s StandalonePluginData SerializeToArray failed!", pluginName.c_str()); 14506f6ba60Sopenharmony_ci } 14606f6ba60Sopenharmony_ci 14706f6ba60Sopenharmony_ci Write(msgData.data(), msgData.size()); 14806f6ba60Sopenharmony_ci} 14906f6ba60Sopenharmony_ci#endif 15006f6ba60Sopenharmony_ci 15106f6ba60Sopenharmony_civoid TraceFileWriter::SetTimeStamp() 15206f6ba60Sopenharmony_ci{ 15306f6ba60Sopenharmony_ci header_.data_.boottime = headerDataTime_.boottime; 15406f6ba60Sopenharmony_ci header_.data_.realtime = headerDataTime_.realtime; 15506f6ba60Sopenharmony_ci header_.data_.realtimeCoarse = headerDataTime_.realtimeCoarse; 15606f6ba60Sopenharmony_ci header_.data_.monotonic = headerDataTime_.monotonic; 15706f6ba60Sopenharmony_ci header_.data_.monotonicCoarse = headerDataTime_.monotonicCoarse; 15806f6ba60Sopenharmony_ci header_.data_.monotonicRaw = headerDataTime_.monotonicRaw; 15906f6ba60Sopenharmony_ci header_.data_.durationNs = headerDataTime_.durationNs; 16006f6ba60Sopenharmony_ci} 16106f6ba60Sopenharmony_ci 16206f6ba60Sopenharmony_civoid TraceFileWriter::SetTimeSource() 16306f6ba60Sopenharmony_ci{ 16406f6ba60Sopenharmony_ci constexpr uint64_t nanoSeconds = 1000000000; 16506f6ba60Sopenharmony_ci struct timespec ts; 16606f6ba60Sopenharmony_ci clock_gettime(CLOCK_BOOTTIME, &ts); 16706f6ba60Sopenharmony_ci headerDataTime_.boottime = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + 16806f6ba60Sopenharmony_ci static_cast<uint64_t>(ts.tv_nsec); 16906f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &ts); 17006f6ba60Sopenharmony_ci headerDataTime_.realtime = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + 17106f6ba60Sopenharmony_ci static_cast<uint64_t>(ts.tv_nsec); 17206f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME_COARSE, &ts); 17306f6ba60Sopenharmony_ci headerDataTime_.realtimeCoarse = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + 17406f6ba60Sopenharmony_ci static_cast<uint64_t>(ts.tv_nsec); 17506f6ba60Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &ts); 17606f6ba60Sopenharmony_ci headerDataTime_.monotonic = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + 17706f6ba60Sopenharmony_ci static_cast<uint64_t>(ts.tv_nsec); 17806f6ba60Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); 17906f6ba60Sopenharmony_ci headerDataTime_.monotonicCoarse = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + 18006f6ba60Sopenharmony_ci static_cast<uint64_t>(ts.tv_nsec); 18106f6ba60Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC_RAW, &ts); 18206f6ba60Sopenharmony_ci headerDataTime_.monotonicRaw = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + 18306f6ba60Sopenharmony_ci static_cast<uint64_t>(ts.tv_nsec); 18406f6ba60Sopenharmony_ci} 18506f6ba60Sopenharmony_ci 18606f6ba60Sopenharmony_civoid TraceFileWriter::SetDurationTime() 18706f6ba60Sopenharmony_ci{ 18806f6ba60Sopenharmony_ci struct timespec ts; 18906f6ba60Sopenharmony_ci clock_gettime(CLOCK_BOOTTIME, &ts); 19006f6ba60Sopenharmony_ci constexpr uint64_t nanoSeconds = 1000000000; 19106f6ba60Sopenharmony_ci auto currBoottime = static_cast<uint64_t>(ts.tv_sec) * nanoSeconds + static_cast<uint64_t>(ts.tv_nsec); 19206f6ba60Sopenharmony_ci headerDataTime_.durationNs = currBoottime - headerDataTime_.boottime; 19306f6ba60Sopenharmony_ci} 19406f6ba60Sopenharmony_ci 19506f6ba60Sopenharmony_cibool TraceFileWriter::WriteHeader() 19606f6ba60Sopenharmony_ci{ 19706f6ba60Sopenharmony_ci LogDiskUsage(); 19806f6ba60Sopenharmony_ci if (isSplitFile_) { 19906f6ba60Sopenharmony_ci std::string timeStr = COMMON::GetTimeStr(); 20006f6ba60Sopenharmony_ci std::size_t pos = oldPath_.find_last_of('.'); 20106f6ba60Sopenharmony_ci if (pos != std::string::npos) { 20206f6ba60Sopenharmony_ci path_ = oldPath_.substr(0, pos) + "_" + timeStr + "_" + std::to_string(fileNum_) + 20306f6ba60Sopenharmony_ci oldPath_.substr(pos, oldPath_.size()); 20406f6ba60Sopenharmony_ci } else { 20506f6ba60Sopenharmony_ci path_ = oldPath_ + "_" + timeStr + "_" + std::to_string(fileNum_); 20606f6ba60Sopenharmony_ci } 20706f6ba60Sopenharmony_ci splitFilePaths_.push(path_); 20806f6ba60Sopenharmony_ci DeleteOldSplitFile(); 20906f6ba60Sopenharmony_ci } 21006f6ba60Sopenharmony_ci 21106f6ba60Sopenharmony_ci stream_ = std::ofstream(path_, std::ios_base::out | std::ios_base::binary); 21206f6ba60Sopenharmony_ci CHECK_TRUE(stream_.is_open(), false, "open %s failed, %d!", path_.c_str(), errno); 21306f6ba60Sopenharmony_ci 21406f6ba60Sopenharmony_ci // write initial header, makes file write position move forward 21506f6ba60Sopenharmony_ci helper_ = {}; 21606f6ba60Sopenharmony_ci header_ = {}; 21706f6ba60Sopenharmony_ci stream_.write(reinterpret_cast<CharPtr>(&header_), sizeof(header_)); 21806f6ba60Sopenharmony_ci CHECK_TRUE(stream_, false, "write initial header to %s failed!", path_.c_str()); 21906f6ba60Sopenharmony_ci dataSize_ = header_.HEADER_SIZE; 22006f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "write file(%s) header end", path_.c_str()); 22106f6ba60Sopenharmony_ci return true; 22206f6ba60Sopenharmony_ci} 22306f6ba60Sopenharmony_ci 22406f6ba60Sopenharmony_ci// delete first split file if split file num over max 22506f6ba60Sopenharmony_civoid TraceFileWriter::DeleteOldSplitFile() 22606f6ba60Sopenharmony_ci{ 22706f6ba60Sopenharmony_ci if (splitFilePaths_.size() <= splitFileMaxNum_) { 22806f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "splitFilePaths_ size %zu, no need to delete.", splitFilePaths_.size()); 22906f6ba60Sopenharmony_ci return; 23006f6ba60Sopenharmony_ci } 23106f6ba60Sopenharmony_ci 23206f6ba60Sopenharmony_ci std::string splitFilePath = splitFilePaths_.front(); 23306f6ba60Sopenharmony_ci int ret = unlink(splitFilePath.c_str()); 23406f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "DeleteOldSplitFile remove %s return %d. ", splitFilePath.c_str(), ret); 23506f6ba60Sopenharmony_ci splitFilePaths_.pop(); 23606f6ba60Sopenharmony_ci} 23706f6ba60Sopenharmony_ci 23806f6ba60Sopenharmony_cilong TraceFileWriter::Write(const void* data, size_t size) 23906f6ba60Sopenharmony_ci{ 24006f6ba60Sopenharmony_ci if (isSplitFile_ && !isStop_) { 24106f6ba60Sopenharmony_ci if (IsSplitFile(size)) { 24206f6ba60Sopenharmony_ci return -1; 24306f6ba60Sopenharmony_ci } 24406f6ba60Sopenharmony_ci } 24506f6ba60Sopenharmony_ci 24606f6ba60Sopenharmony_ci uint32_t dataLen = size; 24706f6ba60Sopenharmony_ci CHECK_TRUE(stream_.is_open(), 0, "binary file %s not open or open failed!", path_.c_str()); 24806f6ba60Sopenharmony_ci 24906f6ba60Sopenharmony_ci // write 4B data length. 25006f6ba60Sopenharmony_ci stream_.write(reinterpret_cast<CharPtr>(&dataLen), sizeof(dataLen)); 25106f6ba60Sopenharmony_ci CHECK_TRUE(stream_, 0, "binary file %s write raw buffer size failed!", path_.c_str()); 25206f6ba60Sopenharmony_ci CHECK_TRUE(helper_.AddSegment(reinterpret_cast<uint8_t*>(&dataLen), sizeof(dataLen)), 25306f6ba60Sopenharmony_ci 0, "Add payload for size %u FAILED!", dataLen); 25406f6ba60Sopenharmony_ci 25506f6ba60Sopenharmony_ci // write data bytes 25606f6ba60Sopenharmony_ci stream_.write(reinterpret_cast<ConstCharPtr>(data), size); 25706f6ba60Sopenharmony_ci CHECK_TRUE(stream_, 0, "binary file %s write raw buffer data failed!", path_.c_str()); 25806f6ba60Sopenharmony_ci 25906f6ba60Sopenharmony_ci CHECK_TRUE(helper_.AddSegment(reinterpret_cast<uint8_t*>(const_cast<void*>(data)), size), 26006f6ba60Sopenharmony_ci 0, "Add payload for data bytes %zu FAILED!", size); 26106f6ba60Sopenharmony_ci 26206f6ba60Sopenharmony_ci uint64_t nbytes = sizeof(dataLen) + size; 26306f6ba60Sopenharmony_ci writeBytes_ += nbytes; 26406f6ba60Sopenharmony_ci ++writeCount_; 26506f6ba60Sopenharmony_ci return nbytes; 26606f6ba60Sopenharmony_ci} 26706f6ba60Sopenharmony_ci 26806f6ba60Sopenharmony_cilong TraceFileWriter::WriteStandalonePluginFile(const std::string &file, 26906f6ba60Sopenharmony_ci const std::string &name, 27006f6ba60Sopenharmony_ci const std::string &version, 27106f6ba60Sopenharmony_ci DataType type) 27206f6ba60Sopenharmony_ci{ 27306f6ba60Sopenharmony_ci CHECK_TRUE(stream_.is_open(), 0, "binary file %s not open or open failed!", path_.c_str()); 27406f6ba60Sopenharmony_ci auto retFile = COMMON::CheckNotExistsFilePath(file); 27506f6ba60Sopenharmony_ci if (!retFile.first) { 27606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:check file path %s fail", __func__, file.c_str()); 27706f6ba60Sopenharmony_ci return 0; 27806f6ba60Sopenharmony_ci } 27906f6ba60Sopenharmony_ci std::ifstream fsFile {}; // read data from file 28006f6ba60Sopenharmony_ci fsFile.open(retFile.second, std::ios_base::in | std::ios_base::binary); 28106f6ba60Sopenharmony_ci if (!fsFile.good()) { 28206f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "open file(%s) failed: %d", file.c_str(), fsFile.rdstate()); 28306f6ba60Sopenharmony_ci return 0; 28406f6ba60Sopenharmony_ci } 28506f6ba60Sopenharmony_ci TraceFileHeader header {}; 28606f6ba60Sopenharmony_ci fsFile.seekg(0, std::ios_base::end); 28706f6ba60Sopenharmony_ci uint64_t fileSize = static_cast<uint64_t>(fsFile.tellg()); 28806f6ba60Sopenharmony_ci header.data_.length += fileSize; 28906f6ba60Sopenharmony_ci size_t size = name.size(); 29006f6ba60Sopenharmony_ci if (size > 0) { 29106f6ba60Sopenharmony_ci if (size > PLUGIN_MODULE_NAME_MAX) { 29206f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "standalonePluginName(%s) size(%zu) is greater than %d!", 29306f6ba60Sopenharmony_ci name.c_str(), size, PLUGIN_MODULE_NAME_MAX); 29406f6ba60Sopenharmony_ci } else if (strncpy_s(header.data_.standalonePluginName, PLUGIN_MODULE_NAME_MAX, name.c_str(), size) != EOK) { 29506f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "strncpy_s standalonePluginName(%s) error!", name.c_str()); 29606f6ba60Sopenharmony_ci } 29706f6ba60Sopenharmony_ci } 29806f6ba60Sopenharmony_ci size = version.size(); 29906f6ba60Sopenharmony_ci if (size > 0) { 30006f6ba60Sopenharmony_ci if (size > PLUGIN_MODULE_VERSION_MAX) { 30106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "pluginVersion(%s) size(%zu) is greater than %d!", 30206f6ba60Sopenharmony_ci version.c_str(), size, PLUGIN_MODULE_VERSION_MAX); 30306f6ba60Sopenharmony_ci } else if (strncpy_s(header.data_.pluginVersion, PLUGIN_MODULE_VERSION_MAX, version.c_str(), size) != EOK) { 30406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "strncpy_s pluginVersion(%s) error!", version.c_str()); 30506f6ba60Sopenharmony_ci } 30606f6ba60Sopenharmony_ci } 30706f6ba60Sopenharmony_ci header.data_.dataType = type; 30806f6ba60Sopenharmony_ci stream_.write(reinterpret_cast<char*>(&header), sizeof(header)); 30906f6ba60Sopenharmony_ci 31006f6ba60Sopenharmony_ci constexpr uint64_t readBufSize = 4 * 1024 * 1024; 31106f6ba60Sopenharmony_ci std::vector<char> readBuf(readBufSize); 31206f6ba60Sopenharmony_ci uint64_t readSize = 0; 31306f6ba60Sopenharmony_ci fsFile.seekg(0); 31406f6ba60Sopenharmony_ci while ((readSize = std::min(readBufSize, fileSize)) > 0) { 31506f6ba60Sopenharmony_ci fsFile.read(readBuf.data(), readSize); 31606f6ba60Sopenharmony_ci stream_.write(readBuf.data(), readSize); 31706f6ba60Sopenharmony_ci 31806f6ba60Sopenharmony_ci fileSize -= readSize; 31906f6ba60Sopenharmony_ci writeBytes_ += readSize; 32006f6ba60Sopenharmony_ci ++writeCount_; 32106f6ba60Sopenharmony_ci } 32206f6ba60Sopenharmony_ci 32306f6ba60Sopenharmony_ci fsFile.close(); 32406f6ba60Sopenharmony_ci return fileSize; 32506f6ba60Sopenharmony_ci} 32606f6ba60Sopenharmony_ci 32706f6ba60Sopenharmony_cibool TraceFileWriter::IsSplitFile(uint32_t size) 32806f6ba60Sopenharmony_ci{ 32906f6ba60Sopenharmony_ci dataSize_ += sizeof(uint32_t) + size; 33006f6ba60Sopenharmony_ci if (dataSize_ >= splitFileMaxSize_) { 33106f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "need to split the file(%s), data size:%d, size: %d, splitFileMaxSize_:%d", 33206f6ba60Sopenharmony_ci path_.c_str(), dataSize_, size, splitFileMaxSize_); 33306f6ba60Sopenharmony_ci 33406f6ba60Sopenharmony_ci // update old file header 33506f6ba60Sopenharmony_ci SetDurationTime(); 33606f6ba60Sopenharmony_ci Finish(); 33706f6ba60Sopenharmony_ci if (stream_.is_open()) { 33806f6ba60Sopenharmony_ci stream_.close(); 33906f6ba60Sopenharmony_ci } 34006f6ba60Sopenharmony_ci fileNum_++; 34106f6ba60Sopenharmony_ci 34206f6ba60Sopenharmony_ci // write header of the new file 34306f6ba60Sopenharmony_ci if (!WriteHeader()) { 34406f6ba60Sopenharmony_ci return false; 34506f6ba60Sopenharmony_ci } 34606f6ba60Sopenharmony_ci SetTimeSource(); 34706f6ba60Sopenharmony_ci 34806f6ba60Sopenharmony_ci // write the plugin config of the new file 34906f6ba60Sopenharmony_ci for (size_t i = 0; i < pluginConfigsData_.size(); i++) { 35006f6ba60Sopenharmony_ci Write(pluginConfigsData_[i].data(), pluginConfigsData_[i].size()); 35106f6ba60Sopenharmony_ci } 35206f6ba60Sopenharmony_ci Flush(); 35306f6ba60Sopenharmony_ci return true; 35406f6ba60Sopenharmony_ci } 35506f6ba60Sopenharmony_ci return false; 35606f6ba60Sopenharmony_ci} 35706f6ba60Sopenharmony_ci 35806f6ba60Sopenharmony_cilong TraceFileWriter::Write(const MessageLite& message) 35906f6ba60Sopenharmony_ci{ 36006f6ba60Sopenharmony_ci auto size = message.ByteSizeLong(); 36106f6ba60Sopenharmony_ci if (isSplitFile_ && !isStop_) { 36206f6ba60Sopenharmony_ci if (IsSplitFile(size)) { 36306f6ba60Sopenharmony_ci return -1; 36406f6ba60Sopenharmony_ci } 36506f6ba60Sopenharmony_ci } 36606f6ba60Sopenharmony_ci 36706f6ba60Sopenharmony_ci // serialize message to bytes array 36806f6ba60Sopenharmony_ci std::vector<char> msgData(size); 36906f6ba60Sopenharmony_ci CHECK_TRUE(message.SerializeToArray(msgData.data(), msgData.size()), 0, "SerializeToArray failed!"); 37006f6ba60Sopenharmony_ci 37106f6ba60Sopenharmony_ci return Write(msgData.data(), msgData.size()); 37206f6ba60Sopenharmony_ci} 37306f6ba60Sopenharmony_ci 37406f6ba60Sopenharmony_cibool TraceFileWriter::Finish() 37506f6ba60Sopenharmony_ci{ 37606f6ba60Sopenharmony_ci // update header info 37706f6ba60Sopenharmony_ci helper_.Update(header_); 37806f6ba60Sopenharmony_ci SetTimeStamp(); // add timestamp in header 37906f6ba60Sopenharmony_ci 38006f6ba60Sopenharmony_ci if (fd_ != -1) { 38106f6ba60Sopenharmony_ci if (lseek(fd_, 0, SEEK_SET) == -1) { 38206f6ba60Sopenharmony_ci return false; 38306f6ba60Sopenharmony_ci } 38406f6ba60Sopenharmony_ci auto ret = write(fd_, &header_, sizeof(header_)); 38506f6ba60Sopenharmony_ci CHECK_TRUE(ret == sizeof(header_), false, "write initial header failed!, error: %s", strerror(errno)); 38606f6ba60Sopenharmony_ci CHECK_TRUE(ftruncate(fd_, fileWriteLength_) == 0, false, "ftruncate(%u) failed, error: %s", 38706f6ba60Sopenharmony_ci fileWriteLength_, strerror(errno)); 38806f6ba60Sopenharmony_ci } else { 38906f6ba60Sopenharmony_ci long long filePos = stream_.tellp(); 39006f6ba60Sopenharmony_ci if (filePos == -1) { // -1 :file not open or error 39106f6ba60Sopenharmony_ci return false; 39206f6ba60Sopenharmony_ci } 39306f6ba60Sopenharmony_ci // move write position to begin of file 39406f6ba60Sopenharmony_ci CHECK_TRUE(stream_.is_open(), false, "binary file %s not open or open failed!", path_.c_str()); 39506f6ba60Sopenharmony_ci stream_.seekp(0); 39606f6ba60Sopenharmony_ci CHECK_TRUE(stream_, false, "seek write position to head for %s failed!", path_.c_str()); 39706f6ba60Sopenharmony_ci 39806f6ba60Sopenharmony_ci // write final header 39906f6ba60Sopenharmony_ci stream_.write(reinterpret_cast<CharPtr>(&header_), sizeof(header_)); 40006f6ba60Sopenharmony_ci stream_.seekp(filePos); 40106f6ba60Sopenharmony_ci CHECK_TRUE(stream_, false, "write final header to %s failed!", path_.c_str()); 40206f6ba60Sopenharmony_ci CHECK_TRUE(stream_.flush(), false, "binary file %s flush failed!", path_.c_str()); 40306f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "Finish: %s, bytes: %" PRIu64 ", count: %" PRIu64, path_.c_str(), writeBytes_, 40406f6ba60Sopenharmony_ci writeCount_); 40506f6ba60Sopenharmony_ci } 40606f6ba60Sopenharmony_ci return true; 40706f6ba60Sopenharmony_ci} 40806f6ba60Sopenharmony_ci 40906f6ba60Sopenharmony_cibool TraceFileWriter::Flush() 41006f6ba60Sopenharmony_ci{ 41106f6ba60Sopenharmony_ci return FlushStream(); 41206f6ba60Sopenharmony_ci} 41306f6ba60Sopenharmony_ci 41406f6ba60Sopenharmony_cibool TraceFileWriter::FlushStream() 41506f6ba60Sopenharmony_ci{ 41606f6ba60Sopenharmony_ci if (fd_ == -1) { 41706f6ba60Sopenharmony_ci CHECK_TRUE(stream_.is_open(), false, "binary file %s not open or open failed!", path_.c_str()); 41806f6ba60Sopenharmony_ci CHECK_TRUE(stream_.flush(), false, "binary file %s flush failed!", path_.c_str()); 41906f6ba60Sopenharmony_ci } 42006f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "flush: %s, bytes: %" PRIu64 ", count: %" PRIu64, path_.c_str(), 42106f6ba60Sopenharmony_ci writeBytes_, writeCount_); 42206f6ba60Sopenharmony_ci return true; 42306f6ba60Sopenharmony_ci} 42406f6ba60Sopenharmony_ci 42506f6ba60Sopenharmony_civoid TraceFileWriter::SetStopSplitFile(bool isStop) 42606f6ba60Sopenharmony_ci{ 42706f6ba60Sopenharmony_ci isStop_ = isStop; 42806f6ba60Sopenharmony_ci} 42906f6ba60Sopenharmony_ci 43006f6ba60Sopenharmony_civoid TraceFileWriter::LogDiskUsage() 43106f6ba60Sopenharmony_ci{ 43206f6ba60Sopenharmony_ci std::string diskPath = "/data/local/tmp/"; 43306f6ba60Sopenharmony_ci std::string::size_type pos = oldPath_.find_last_of('/'); 43406f6ba60Sopenharmony_ci if (pos != std::string::npos) { 43506f6ba60Sopenharmony_ci diskPath = oldPath_.substr(0, pos); 43606f6ba60Sopenharmony_ci } 43706f6ba60Sopenharmony_ci 43806f6ba60Sopenharmony_ci struct statvfs diskInfo; 43906f6ba60Sopenharmony_ci int ret = statvfs(diskPath.c_str(), &diskInfo); 44006f6ba60Sopenharmony_ci if (ret != 0) { 44106f6ba60Sopenharmony_ci std::string errorMsg = COMMON::GetErrorMsg(); 44206f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "LogDiskUsage() return %d, path:%s, msg:%s", 44306f6ba60Sopenharmony_ci ret, diskPath.c_str(), errorMsg.c_str()); 44406f6ba60Sopenharmony_ci return; 44506f6ba60Sopenharmony_ci } 44606f6ba60Sopenharmony_ci 44706f6ba60Sopenharmony_ci unsigned long long freeSize = static_cast<unsigned long long>(diskInfo.f_bsize) * 44806f6ba60Sopenharmony_ci static_cast<unsigned long long>(diskInfo.f_bfree); 44906f6ba60Sopenharmony_ci unsigned long long totalSize = static_cast<unsigned long long>(diskInfo.f_bsize) * 45006f6ba60Sopenharmony_ci static_cast<unsigned long long>(diskInfo.f_blocks); 45106f6ba60Sopenharmony_ci float freePercent = 0; 45206f6ba60Sopenharmony_ci if (totalSize != 0) { 45306f6ba60Sopenharmony_ci freePercent = static_cast<float>(freeSize) / static_cast<float>(totalSize); 45406f6ba60Sopenharmony_ci } 45506f6ba60Sopenharmony_ci uint32_t freeSizeGb = freeSize / GB_TO_BYTE; 45606f6ba60Sopenharmony_ci // 100: in terms of percentage 45706f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "LogDiskUsage() freePercent:%.1f, freeSizeGb:%u", freePercent * 100, freeSizeGb); 45806f6ba60Sopenharmony_ci} 45906f6ba60Sopenharmony_ci 46006f6ba60Sopenharmony_cibool TraceFileWriter::RemapFile() 46106f6ba60Sopenharmony_ci{ 46206f6ba60Sopenharmony_ci if (munmap(fileMapAddr_, fileLength_) != 0) { 46306f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "munmap file(%zu) failed, error: %s", fileLength_, strerror(errno)); 46406f6ba60Sopenharmony_ci return false; 46506f6ba60Sopenharmony_ci } 46606f6ba60Sopenharmony_ci 46706f6ba60Sopenharmony_ci // file size increased by DEFULT_PAGES * pageSize_(64M) 46806f6ba60Sopenharmony_ci size_t newLength = fileLength_ + DEFULT_PAGES * pageSize_; 46906f6ba60Sopenharmony_ci if (ftruncate(fd_, newLength) != 0) { 47006f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "ftruncate file(%zu) failed, error: %s", newLength, strerror(errno)); 47106f6ba60Sopenharmony_ci return false; 47206f6ba60Sopenharmony_ci } 47306f6ba60Sopenharmony_ci 47406f6ba60Sopenharmony_ci size_t remapPos = fileWriteLength_ & ~(pageSize_ - 1); 47506f6ba60Sopenharmony_ci fileMapAddr_ = mmap(nullptr, newLength, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_POPULATE, fd_, remapPos); 47606f6ba60Sopenharmony_ci if (fileMapAddr_ == MAP_FAILED) { 47706f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "remap(%zu:%zu) data file failed, error: %s", newLength, remapPos, 47806f6ba60Sopenharmony_ci strerror(errno)); 47906f6ba60Sopenharmony_ci return false; 48006f6ba60Sopenharmony_ci } 48106f6ba60Sopenharmony_ci 48206f6ba60Sopenharmony_ci mapOffset_ = fileWriteLength_ - remapPos; 48306f6ba60Sopenharmony_ci fileLength_ = newLength; 48406f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "remap(%zu:%zu) data file(%zu) sucess", remapPos, mapOffset_, fileLength_); 48506f6ba60Sopenharmony_ci return true; 48606f6ba60Sopenharmony_ci} 48706f6ba60Sopenharmony_ci 48806f6ba60Sopenharmony_cibool TraceFileWriter::GetMemory(uint32_t size, uint8_t** memory, uint32_t* offset) 48906f6ba60Sopenharmony_ci{ 49006f6ba60Sopenharmony_ci if ((fileWriteLength_ + PIECE_HEAD_LEN + messageWriteOffset_ + size) > fileLength_) { 49106f6ba60Sopenharmony_ci if (!RemapFile()) { 49206f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "RemapFile failed!"); 49306f6ba60Sopenharmony_ci return false; 49406f6ba60Sopenharmony_ci } 49506f6ba60Sopenharmony_ci } 49606f6ba60Sopenharmony_ci 49706f6ba60Sopenharmony_ci *memory = &reinterpret_cast<uint8_t*>(fileMapAddr_)[mapOffset_ + messageWriteOffset_]; 49806f6ba60Sopenharmony_ci *offset = messageWriteOffset_; 49906f6ba60Sopenharmony_ci return true; 50006f6ba60Sopenharmony_ci} 50106f6ba60Sopenharmony_ci 50206f6ba60Sopenharmony_cibool TraceFileWriter::Seek(uint32_t offset) 50306f6ba60Sopenharmony_ci{ 50406f6ba60Sopenharmony_ci messageWriteOffset_ = offset; 50506f6ba60Sopenharmony_ci return true; 50606f6ba60Sopenharmony_ci} 50706f6ba60Sopenharmony_ci 50806f6ba60Sopenharmony_civoid TraceFileWriter::FinishReport(int32_t size) 50906f6ba60Sopenharmony_ci{ 51006f6ba60Sopenharmony_ci auto realSize = PIECE_HEAD_LEN + size; 51106f6ba60Sopenharmony_ci CHECK_TRUE(helper_.AddSegment(nullptr, realSize), NO_RETVAL, "AddSegment(%d) failed, error: %s", 51206f6ba60Sopenharmony_ci realSize, strerror(errno)); 51306f6ba60Sopenharmony_ci 51406f6ba60Sopenharmony_ci // write data length 51506f6ba60Sopenharmony_ci *(reinterpret_cast<int*>((&reinterpret_cast<uint8_t*>(fileMapAddr_)[mapOffset_]))) = size; 51606f6ba60Sopenharmony_ci mapOffset_ += static_cast<uint64_t>(realSize); 51706f6ba60Sopenharmony_ci fileWriteLength_ += static_cast<uint64_t>(realSize); 51806f6ba60Sopenharmony_ci writeBytes_ += static_cast<uint64_t>(realSize); 51906f6ba60Sopenharmony_ci ++writeCount_; 52006f6ba60Sopenharmony_ci} 52106f6ba60Sopenharmony_ci 52206f6ba60Sopenharmony_civoid TraceFileWriter::ResetPos() 52306f6ba60Sopenharmony_ci{ 52406f6ba60Sopenharmony_ci messageWriteOffset_ = PIECE_HEAD_LEN; 52506f6ba60Sopenharmony_ci}