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}