106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. 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 "process_data_plugin.h"
1606f6ba60Sopenharmony_ci
1706f6ba60Sopenharmony_ci#include <fcntl.h>
1806f6ba60Sopenharmony_ci#include <fstream>
1906f6ba60Sopenharmony_ci#include <iostream>
2006f6ba60Sopenharmony_ci#include <sstream>
2106f6ba60Sopenharmony_ci
2206f6ba60Sopenharmony_ci#include "buffer_splitter.h"
2306f6ba60Sopenharmony_ci#include "process_plugin_result.pbencoder.h"
2406f6ba60Sopenharmony_ci#include "securec.h"
2506f6ba60Sopenharmony_ci
2606f6ba60Sopenharmony_cinamespace {
2706f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
2806f6ba60Sopenharmony_ciconstexpr size_t READ_BUFFER_SIZE = 1024 * 16;
2906f6ba60Sopenharmony_ciconstexpr int DEC_BASE = 10;
3006f6ba60Sopenharmony_ciconstexpr int STAT_COUNT = 13;
3106f6ba60Sopenharmony_ciconstexpr int CPU_USER_HZ_L = 100;
3206f6ba60Sopenharmony_ciconstexpr int CPU_USER_HZ_H = 1000;
3306f6ba60Sopenharmony_ciconstexpr int CPU_HZ_H = 10;
3406f6ba60Sopenharmony_ciconst int PERCENT = 100;
3506f6ba60Sopenharmony_ci} // namespace
3606f6ba60Sopenharmony_ci
3706f6ba60Sopenharmony_ciProcessDataPlugin::ProcessDataPlugin() : err_(-1)
3806f6ba60Sopenharmony_ci{
3906f6ba60Sopenharmony_ci    SetPath("/proc/");
4006f6ba60Sopenharmony_ci    buffer_ = std::make_unique<uint8_t[]>(READ_BUFFER_SIZE);
4106f6ba60Sopenharmony_ci}
4206f6ba60Sopenharmony_ci
4306f6ba60Sopenharmony_ciProcessDataPlugin::~ProcessDataPlugin()
4406f6ba60Sopenharmony_ci{
4506f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:~ProcessDataPlugin!", __func__);
4606f6ba60Sopenharmony_ci
4706f6ba60Sopenharmony_ci    buffer_ = nullptr;
4806f6ba60Sopenharmony_ci
4906f6ba60Sopenharmony_ci    return;
5006f6ba60Sopenharmony_ci}
5106f6ba60Sopenharmony_ci
5206f6ba60Sopenharmony_ciint ProcessDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
5306f6ba60Sopenharmony_ci{
5406f6ba60Sopenharmony_ci    CHECK_NOTNULL(buffer_, RET_FAIL, "%s:buffer_ == null", __func__);
5506f6ba60Sopenharmony_ci
5606f6ba60Sopenharmony_ci    CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, RET_FAIL,
5706f6ba60Sopenharmony_ci               "%s:parseFromArray failed!", __func__);
5806f6ba60Sopenharmony_ci
5906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:start success!", __func__);
6006f6ba60Sopenharmony_ci    return RET_SUCC;
6106f6ba60Sopenharmony_ci}
6206f6ba60Sopenharmony_ci
6306f6ba60Sopenharmony_ciint ProcessDataPlugin::ReportOptimize(RandomWriteCtx* randomWrite)
6406f6ba60Sopenharmony_ci{
6506f6ba60Sopenharmony_ci    ProtoEncoder::ProcessData dataProto(randomWrite);
6606f6ba60Sopenharmony_ci    if (protoConfig_.report_process_tree()) {
6706f6ba60Sopenharmony_ci        WriteProcesseList(dataProto);
6806f6ba60Sopenharmony_ci    }
6906f6ba60Sopenharmony_ci
7006f6ba60Sopenharmony_ci    int msgSize = dataProto.Finish();
7106f6ba60Sopenharmony_ci    return msgSize;
7206f6ba60Sopenharmony_ci}
7306f6ba60Sopenharmony_ci
7406f6ba60Sopenharmony_ciint ProcessDataPlugin::Report(uint8_t* data, uint32_t dataSize)
7506f6ba60Sopenharmony_ci{
7606f6ba60Sopenharmony_ci    ProcessData dataProto;
7706f6ba60Sopenharmony_ci    uint32_t length;
7806f6ba60Sopenharmony_ci
7906f6ba60Sopenharmony_ci    if (protoConfig_.report_process_tree()) {
8006f6ba60Sopenharmony_ci        WriteProcesseList(dataProto);
8106f6ba60Sopenharmony_ci    }
8206f6ba60Sopenharmony_ci
8306f6ba60Sopenharmony_ci    length = dataProto.ByteSizeLong();
8406f6ba60Sopenharmony_ci    if (length > dataSize) {
8506f6ba60Sopenharmony_ci        return -length;
8606f6ba60Sopenharmony_ci    }
8706f6ba60Sopenharmony_ci    if (dataProto.SerializeToArray(data, length) > 0) {
8806f6ba60Sopenharmony_ci        return length;
8906f6ba60Sopenharmony_ci    }
9006f6ba60Sopenharmony_ci    return 0;
9106f6ba60Sopenharmony_ci}
9206f6ba60Sopenharmony_ci
9306f6ba60Sopenharmony_ciint ProcessDataPlugin::Stop()
9406f6ba60Sopenharmony_ci{
9506f6ba60Sopenharmony_ci    pids_.clear();
9606f6ba60Sopenharmony_ci    cpuTime_.clear();
9706f6ba60Sopenharmony_ci    bootTime_.clear();
9806f6ba60Sopenharmony_ci
9906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:stop success!", __func__);
10006f6ba60Sopenharmony_ci    return 0;
10106f6ba60Sopenharmony_ci}
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_ciDIR* ProcessDataPlugin::OpenDestDir(const char* dirPath)
10406f6ba60Sopenharmony_ci{
10506f6ba60Sopenharmony_ci    DIR* destDir = nullptr;
10606f6ba60Sopenharmony_ci
10706f6ba60Sopenharmony_ci    destDir = opendir(dirPath);
10806f6ba60Sopenharmony_ci    if (destDir == nullptr) {
10906f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to opendir(%s), errno=%d", __func__, dirPath, errno);
11006f6ba60Sopenharmony_ci    }
11106f6ba60Sopenharmony_ci
11206f6ba60Sopenharmony_ci    return destDir;
11306f6ba60Sopenharmony_ci}
11406f6ba60Sopenharmony_ci
11506f6ba60Sopenharmony_ciint32_t ProcessDataPlugin::GetValidPid(DIR* dirp)
11606f6ba60Sopenharmony_ci{
11706f6ba60Sopenharmony_ci    if (!dirp) {
11806f6ba60Sopenharmony_ci        return 0;
11906f6ba60Sopenharmony_ci    }
12006f6ba60Sopenharmony_ci    while (struct dirent* dirEnt = readdir(dirp)) {
12106f6ba60Sopenharmony_ci        if (dirEnt->d_type != DT_DIR) {
12206f6ba60Sopenharmony_ci            continue;
12306f6ba60Sopenharmony_ci        }
12406f6ba60Sopenharmony_ci
12506f6ba60Sopenharmony_ci        int32_t pid = atoi(dirEnt->d_name);
12606f6ba60Sopenharmony_ci        if (pid) {
12706f6ba60Sopenharmony_ci            return pid;
12806f6ba60Sopenharmony_ci        }
12906f6ba60Sopenharmony_ci    }
13006f6ba60Sopenharmony_ci    return 0;
13106f6ba60Sopenharmony_ci}
13206f6ba60Sopenharmony_ci
13306f6ba60Sopenharmony_ciint32_t ProcessDataPlugin::ReadProcPidFile(int32_t pid, const char* pFileName)
13406f6ba60Sopenharmony_ci{
13506f6ba60Sopenharmony_ci    char fileName[PATH_MAX + 1] = {0};
13606f6ba60Sopenharmony_ci    char realPath[PATH_MAX + 1] = {0};
13706f6ba60Sopenharmony_ci    int fd = -1;
13806f6ba60Sopenharmony_ci    ssize_t bytesRead = 0;
13906f6ba60Sopenharmony_ci
14006f6ba60Sopenharmony_ci    if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s%d/%s", path_.c_str(), pid, pFileName) < 0) {
14106f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:snprintf_s error", __func__);
14206f6ba60Sopenharmony_ci    }
14306f6ba60Sopenharmony_ci    if (realpath(fileName, realPath) == nullptr) {
14406f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:realpath failed, errno=%d", __func__, errno);
14506f6ba60Sopenharmony_ci        return RET_FAIL;
14606f6ba60Sopenharmony_ci    }
14706f6ba60Sopenharmony_ci    fd = open(realPath, O_RDONLY | O_CLOEXEC);
14806f6ba60Sopenharmony_ci    if (fd == -1) {
14906f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "%s:failed to open(%s), errno=%d", __func__, fileName, errno);
15006f6ba60Sopenharmony_ci        err_ = errno;
15106f6ba60Sopenharmony_ci        return RET_FAIL;
15206f6ba60Sopenharmony_ci    }
15306f6ba60Sopenharmony_ci    if (buffer_.get() == nullptr) {
15406f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "%s:empty address, buffer_ is NULL", __func__);
15506f6ba60Sopenharmony_ci        err_ = RET_NULL_ADDR;
15606f6ba60Sopenharmony_ci        close(fd);
15706f6ba60Sopenharmony_ci        return RET_FAIL;
15806f6ba60Sopenharmony_ci    }
15906f6ba60Sopenharmony_ci    bytesRead = read(fd, buffer_.get(), READ_BUFFER_SIZE - 1);
16006f6ba60Sopenharmony_ci    if (bytesRead < 0) {
16106f6ba60Sopenharmony_ci        close(fd);
16206f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "%s:failed to read(%s), errno=%d", __func__, fileName, errno);
16306f6ba60Sopenharmony_ci        err_ = errno;
16406f6ba60Sopenharmony_ci        return RET_FAIL;
16506f6ba60Sopenharmony_ci    }
16606f6ba60Sopenharmony_ci    buffer_.get()[bytesRead] = '\0';
16706f6ba60Sopenharmony_ci    close(fd);
16806f6ba60Sopenharmony_ci
16906f6ba60Sopenharmony_ci    return bytesRead;
17006f6ba60Sopenharmony_ci}
17106f6ba60Sopenharmony_ci
17206f6ba60Sopenharmony_cibool ProcessDataPlugin::BufnCmp(const char* src, int srcLen, const char* key, int keyLen)
17306f6ba60Sopenharmony_ci{
17406f6ba60Sopenharmony_ci    if (!src || !key || (srcLen < keyLen)) {
17506f6ba60Sopenharmony_ci        return false;
17606f6ba60Sopenharmony_ci    }
17706f6ba60Sopenharmony_ci    for (int i = 0; i < keyLen; i++) {
17806f6ba60Sopenharmony_ci        if (*src++ != *key++) {
17906f6ba60Sopenharmony_ci            return false;
18006f6ba60Sopenharmony_ci        }
18106f6ba60Sopenharmony_ci    }
18206f6ba60Sopenharmony_ci    return true;
18306f6ba60Sopenharmony_ci}
18406f6ba60Sopenharmony_ci
18506f6ba60Sopenharmony_cibool ProcessDataPlugin::addPidBySort(int32_t pid)
18606f6ba60Sopenharmony_ci{
18706f6ba60Sopenharmony_ci    auto pidsEnd = pids_.end();
18806f6ba60Sopenharmony_ci    auto it = std::lower_bound(pids_.begin(), pidsEnd, pid);
18906f6ba60Sopenharmony_ci    if (it != pidsEnd && *it == pid) {
19006f6ba60Sopenharmony_ci        return false;
19106f6ba60Sopenharmony_ci    }
19206f6ba60Sopenharmony_ci    it = pids_.insert(it, std::move(pid));
19306f6ba60Sopenharmony_ci    return true;
19406f6ba60Sopenharmony_ci}
19506f6ba60Sopenharmony_ci
19606f6ba60Sopenharmony_citemplate <typename T>
19706f6ba60Sopenharmony_civoid ProcessDataPlugin::WriteProcess(T& processinfo, const char* pFile, uint32_t fileLen, int32_t pid)
19806f6ba60Sopenharmony_ci{
19906f6ba60Sopenharmony_ci    BufferSplitter totalbuffer(const_cast<const char*>(pFile), fileLen + 1);
20006f6ba60Sopenharmony_ci
20106f6ba60Sopenharmony_ci    do {
20206f6ba60Sopenharmony_ci        totalbuffer.NextWord(':');
20306f6ba60Sopenharmony_ci        if (!totalbuffer.CurWord()) {
20406f6ba60Sopenharmony_ci            return;
20506f6ba60Sopenharmony_ci        }
20606f6ba60Sopenharmony_ci
20706f6ba60Sopenharmony_ci        if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "Name", strlen("Name"))) {
20806f6ba60Sopenharmony_ci            totalbuffer.NextWord('\n');
20906f6ba60Sopenharmony_ci            if (!totalbuffer.CurWord()) {
21006f6ba60Sopenharmony_ci                return;
21106f6ba60Sopenharmony_ci            }
21206f6ba60Sopenharmony_ci            processinfo.set_name(totalbuffer.CurWord(), totalbuffer.CurWordSize());
21306f6ba60Sopenharmony_ci        } else if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "Pid", strlen("Pid"))) {
21406f6ba60Sopenharmony_ci            totalbuffer.NextWord('\n');
21506f6ba60Sopenharmony_ci            if (!totalbuffer.CurWord()) {
21606f6ba60Sopenharmony_ci                return;
21706f6ba60Sopenharmony_ci            }
21806f6ba60Sopenharmony_ci            char* end = nullptr;
21906f6ba60Sopenharmony_ci            int32_t value = static_cast<int32_t>(strtoul(totalbuffer.CurWord(), &end, DEC_BASE));
22006f6ba60Sopenharmony_ci            if (value < 0) {
22106f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "%s:strtoull value failed", __func__);
22206f6ba60Sopenharmony_ci            }
22306f6ba60Sopenharmony_ci            processinfo.set_pid(value);
22406f6ba60Sopenharmony_ci        } else if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "PPid", strlen("PPid"))) {
22506f6ba60Sopenharmony_ci            totalbuffer.NextWord('\n');
22606f6ba60Sopenharmony_ci            if (!totalbuffer.CurWord()) {
22706f6ba60Sopenharmony_ci                return;
22806f6ba60Sopenharmony_ci            }
22906f6ba60Sopenharmony_ci            char* end = nullptr;
23006f6ba60Sopenharmony_ci            int32_t value = static_cast<int32_t>(strtoul(totalbuffer.CurWord(), &end, DEC_BASE));
23106f6ba60Sopenharmony_ci            if (value < 0) {
23206f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "%s:strtoull value failed", __func__);
23306f6ba60Sopenharmony_ci            }
23406f6ba60Sopenharmony_ci            processinfo.set_ppid(value);
23506f6ba60Sopenharmony_ci        } else if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "Uid", strlen("Uid"))) {
23606f6ba60Sopenharmony_ci            totalbuffer.NextWord('\n');
23706f6ba60Sopenharmony_ci            if (!totalbuffer.CurWord()) {
23806f6ba60Sopenharmony_ci                return;
23906f6ba60Sopenharmony_ci            }
24006f6ba60Sopenharmony_ci            std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
24106f6ba60Sopenharmony_ci            curWord = curWord.substr(0, curWord.find(" "));
24206f6ba60Sopenharmony_ci            char* end = nullptr;
24306f6ba60Sopenharmony_ci            int32_t value = static_cast<int32_t>(strtoul(curWord.c_str(), &end, DEC_BASE));
24406f6ba60Sopenharmony_ci            if (value < 0) {
24506f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "%s:strtoull value failed", __func__);
24606f6ba60Sopenharmony_ci            }
24706f6ba60Sopenharmony_ci            processinfo.set_uid(value);
24806f6ba60Sopenharmony_ci            break;
24906f6ba60Sopenharmony_ci        } else {
25006f6ba60Sopenharmony_ci            totalbuffer.NextWord('\n');
25106f6ba60Sopenharmony_ci            if (!totalbuffer.CurWord()) {
25206f6ba60Sopenharmony_ci                continue;
25306f6ba60Sopenharmony_ci            }
25406f6ba60Sopenharmony_ci        }
25506f6ba60Sopenharmony_ci    } while (totalbuffer.NextLine());
25606f6ba60Sopenharmony_ci    // update process name
25706f6ba60Sopenharmony_ci    int32_t ret = ReadProcPidFile(pid, "cmdline");
25806f6ba60Sopenharmony_ci    if (ret > 0) {
25906f6ba60Sopenharmony_ci        processinfo.set_name(reinterpret_cast<char*>(buffer_.get()), strlen(reinterpret_cast<char*>(buffer_.get())));
26006f6ba60Sopenharmony_ci    }
26106f6ba60Sopenharmony_ci}
26206f6ba60Sopenharmony_ci
26306f6ba60Sopenharmony_citemplate <typename T> void ProcessDataPlugin::WriteProcessInfo(T& processData, int32_t pid)
26406f6ba60Sopenharmony_ci{
26506f6ba60Sopenharmony_ci    int32_t ret = ReadProcPidFile(pid, "status");
26606f6ba60Sopenharmony_ci    if (ret == RET_FAIL) {
26706f6ba60Sopenharmony_ci        return;
26806f6ba60Sopenharmony_ci    }
26906f6ba60Sopenharmony_ci    if ((buffer_.get() == nullptr) || (ret == 0)) {
27006f6ba60Sopenharmony_ci        return;
27106f6ba60Sopenharmony_ci    }
27206f6ba60Sopenharmony_ci    auto* processinfo = processData.add_processesinfo();
27306f6ba60Sopenharmony_ci    WriteProcess(*processinfo, reinterpret_cast<char*>(buffer_.get()), ret, pid);
27406f6ba60Sopenharmony_ci    if (protoConfig_.report_cpu()) {
27506f6ba60Sopenharmony_ci        auto* cpuInfo = processinfo->mutable_cpuinfo();
27606f6ba60Sopenharmony_ci        std::vector<uint64_t> cpuUsageVec;
27706f6ba60Sopenharmony_ci        std::vector<uint64_t> bootTime;
27806f6ba60Sopenharmony_ci        WriteCpuUsageData(pid, *cpuInfo);
27906f6ba60Sopenharmony_ci        WriteThreadData(pid, *cpuInfo);
28006f6ba60Sopenharmony_ci    }
28106f6ba60Sopenharmony_ci    if (protoConfig_.report_diskio()) {
28206f6ba60Sopenharmony_ci        WriteDiskioData(pid, *processinfo);
28306f6ba60Sopenharmony_ci    }
28406f6ba60Sopenharmony_ci    if (protoConfig_.report_pss()) {
28506f6ba60Sopenharmony_ci        WritePssData(pid, *processinfo);
28606f6ba60Sopenharmony_ci    }
28706f6ba60Sopenharmony_ci}
28806f6ba60Sopenharmony_ci
28906f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteProcesseList(T& processData)
29006f6ba60Sopenharmony_ci{
29106f6ba60Sopenharmony_ci    DIR* procDir = nullptr;
29206f6ba60Sopenharmony_ci
29306f6ba60Sopenharmony_ci    procDir = OpenDestDir(path_.c_str());
29406f6ba60Sopenharmony_ci    if (procDir == nullptr) {
29506f6ba60Sopenharmony_ci        return false;
29606f6ba60Sopenharmony_ci    }
29706f6ba60Sopenharmony_ci
29806f6ba60Sopenharmony_ci    pids_.clear();
29906f6ba60Sopenharmony_ci    while (int32_t pid = GetValidPid(procDir)) {
30006f6ba60Sopenharmony_ci        if (pid <= 0) {
30106f6ba60Sopenharmony_ci            closedir(procDir);
30206f6ba60Sopenharmony_ci            PROFILER_LOG_WARN(LOG_CORE, "%s: get pid[%d] failed", __func__, pid);
30306f6ba60Sopenharmony_ci            return false;
30406f6ba60Sopenharmony_ci        }
30506f6ba60Sopenharmony_ci        addPidBySort(pid);
30606f6ba60Sopenharmony_ci    }
30706f6ba60Sopenharmony_ci
30806f6ba60Sopenharmony_ci    for (unsigned int i = 0; i < pids_.size(); i++) {
30906f6ba60Sopenharmony_ci        WriteProcessInfo(processData, pids_[i]);
31006f6ba60Sopenharmony_ci    }
31106f6ba60Sopenharmony_ci
31206f6ba60Sopenharmony_ci    closedir(procDir);
31306f6ba60Sopenharmony_ci    return true;
31406f6ba60Sopenharmony_ci}
31506f6ba60Sopenharmony_ci
31606f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteThreadData(int pid, T& cpuInfo)
31706f6ba60Sopenharmony_ci{
31806f6ba60Sopenharmony_ci    DIR* procDir = nullptr;
31906f6ba60Sopenharmony_ci    std::string path = path_ + std::to_string(pid) + "/task";
32006f6ba60Sopenharmony_ci    procDir = OpenDestDir(path.c_str());
32106f6ba60Sopenharmony_ci    if (procDir == nullptr) {
32206f6ba60Sopenharmony_ci        return false;
32306f6ba60Sopenharmony_ci    }
32406f6ba60Sopenharmony_ci
32506f6ba60Sopenharmony_ci    uint32_t i = 0;
32606f6ba60Sopenharmony_ci    while (int32_t tid = GetValidPid(procDir)) {
32706f6ba60Sopenharmony_ci        if (tid <= 0) {
32806f6ba60Sopenharmony_ci            closedir(procDir);
32906f6ba60Sopenharmony_ci            PROFILER_LOG_WARN(LOG_CORE, "%s: get pid[%d] failed", __func__, tid);
33006f6ba60Sopenharmony_ci            return false;
33106f6ba60Sopenharmony_ci        }
33206f6ba60Sopenharmony_ci        i++;
33306f6ba60Sopenharmony_ci    }
33406f6ba60Sopenharmony_ci    cpuInfo.set_thread_sum(i);
33506f6ba60Sopenharmony_ci    closedir(procDir);
33606f6ba60Sopenharmony_ci    return true;
33706f6ba60Sopenharmony_ci}
33806f6ba60Sopenharmony_ci
33906f6ba60Sopenharmony_ciint64_t ProcessDataPlugin::GetUserHz()
34006f6ba60Sopenharmony_ci{
34106f6ba60Sopenharmony_ci    int64_t hz = -1;
34206f6ba60Sopenharmony_ci    int64_t user_hz = sysconf(_SC_CLK_TCK);
34306f6ba60Sopenharmony_ci    switch (user_hz) {
34406f6ba60Sopenharmony_ci        case CPU_USER_HZ_L:
34506f6ba60Sopenharmony_ci            hz = CPU_HZ_H;
34606f6ba60Sopenharmony_ci            break;
34706f6ba60Sopenharmony_ci        case CPU_USER_HZ_H:
34806f6ba60Sopenharmony_ci            hz = 1;
34906f6ba60Sopenharmony_ci            break;
35006f6ba60Sopenharmony_ci        default:
35106f6ba60Sopenharmony_ci            break;
35206f6ba60Sopenharmony_ci    }
35306f6ba60Sopenharmony_ci    return hz;
35406f6ba60Sopenharmony_ci}
35506f6ba60Sopenharmony_ci
35606f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteCpuUsageData(int pid, T& cpuInfo)
35706f6ba60Sopenharmony_ci{
35806f6ba60Sopenharmony_ci    uint64_t prevCpuTime = 0;
35906f6ba60Sopenharmony_ci    uint64_t cpuTime = 0;
36006f6ba60Sopenharmony_ci    uint64_t prevBootTime = 0;
36106f6ba60Sopenharmony_ci    uint64_t bootTime = 0;
36206f6ba60Sopenharmony_ci    double usage = 0.0;
36306f6ba60Sopenharmony_ci    ReadCpuUsage(pid, cpuTime);
36406f6ba60Sopenharmony_ci    ReadBootTime(pid, bootTime);
36506f6ba60Sopenharmony_ci    if (cpuTime_.find(pid) != cpuTime_.end()) {
36606f6ba60Sopenharmony_ci        prevCpuTime = cpuTime_[pid];
36706f6ba60Sopenharmony_ci    }
36806f6ba60Sopenharmony_ci    if (bootTime_.find(pid) != bootTime_.end()) {
36906f6ba60Sopenharmony_ci        prevBootTime = bootTime_[pid];
37006f6ba60Sopenharmony_ci    }
37106f6ba60Sopenharmony_ci    if (bootTime - prevBootTime == 0 || bootTime == 0) {
37206f6ba60Sopenharmony_ci        return false;
37306f6ba60Sopenharmony_ci    }
37406f6ba60Sopenharmony_ci    if (cpuTime < prevCpuTime) {
37506f6ba60Sopenharmony_ci        return false;
37606f6ba60Sopenharmony_ci    }
37706f6ba60Sopenharmony_ci    if (prevCpuTime == 0) {
37806f6ba60Sopenharmony_ci        usage = static_cast<double>(cpuTime) / (bootTime);
37906f6ba60Sopenharmony_ci    } else {
38006f6ba60Sopenharmony_ci        usage = static_cast<double>(cpuTime - prevCpuTime) / (bootTime - prevBootTime);
38106f6ba60Sopenharmony_ci    }
38206f6ba60Sopenharmony_ci
38306f6ba60Sopenharmony_ci    if (usage > 0) {
38406f6ba60Sopenharmony_ci        cpuInfo.set_cpu_usage(usage * PERCENT);
38506f6ba60Sopenharmony_ci    }
38606f6ba60Sopenharmony_ci    cpuInfo.set_cpu_time_ms(cpuTime);
38706f6ba60Sopenharmony_ci    cpuTime_[pid] = cpuTime;
38806f6ba60Sopenharmony_ci    bootTime_[pid] = bootTime;
38906f6ba60Sopenharmony_ci    return true;
39006f6ba60Sopenharmony_ci}
39106f6ba60Sopenharmony_ci
39206f6ba60Sopenharmony_cibool ProcessDataPlugin::ReadBootTime(int pid, uint64_t& bootTime)
39306f6ba60Sopenharmony_ci{
39406f6ba60Sopenharmony_ci    std::string path = path_ + "stat";
39506f6ba60Sopenharmony_ci    std::ifstream input(path, std::ios::in);
39606f6ba60Sopenharmony_ci    CHECK_TRUE(!input.fail(), false, "%s open %s failed, errno = %d", __func__, path.c_str(), errno);
39706f6ba60Sopenharmony_ci    do {
39806f6ba60Sopenharmony_ci        if (!input.good()) {
39906f6ba60Sopenharmony_ci            return false;
40006f6ba60Sopenharmony_ci        }
40106f6ba60Sopenharmony_ci        std::string line;
40206f6ba60Sopenharmony_ci        getline(input, line);
40306f6ba60Sopenharmony_ci
40406f6ba60Sopenharmony_ci        auto pos = line.find("cpu ");
40506f6ba60Sopenharmony_ci        if (pos != std::string::npos) {
40606f6ba60Sopenharmony_ci            line += '\n';
40706f6ba60Sopenharmony_ci            GetBootData(line, bootTime);
40806f6ba60Sopenharmony_ci        }
40906f6ba60Sopenharmony_ci    } while (0);
41006f6ba60Sopenharmony_ci    input.close();
41106f6ba60Sopenharmony_ci
41206f6ba60Sopenharmony_ci    return true;
41306f6ba60Sopenharmony_ci}
41406f6ba60Sopenharmony_ci
41506f6ba60Sopenharmony_ciuint32_t ProcessDataPlugin::GetBootData(const std::string& line, uint64_t& bootTime)
41606f6ba60Sopenharmony_ci{
41706f6ba60Sopenharmony_ci    uint64_t num;
41806f6ba60Sopenharmony_ci    uint32_t count = 0;
41906f6ba60Sopenharmony_ci    char* end = nullptr;
42006f6ba60Sopenharmony_ci    char* pTmp = const_cast<char*>(line.c_str());
42106f6ba60Sopenharmony_ci    constexpr uint32_t cntVec = 8;
42206f6ba60Sopenharmony_ci
42306f6ba60Sopenharmony_ci    std::vector<uint64_t> bootTimeVec;
42406f6ba60Sopenharmony_ci    bootTime = 0;
42506f6ba60Sopenharmony_ci    while (pTmp != nullptr && *pTmp != '\n') {
42606f6ba60Sopenharmony_ci        CHECK_TRUE(FindFirstNum(&pTmp), count, "%s: FindFirstNum failed", __func__);
42706f6ba60Sopenharmony_ci        num = strtoull(pTmp, &end, DEC_BASE);
42806f6ba60Sopenharmony_ci        CHECK_TRUE(num >= 0, count, "%s:strtoull failed", __func__);
42906f6ba60Sopenharmony_ci        bootTimeVec.push_back(num);
43006f6ba60Sopenharmony_ci        bootTime += num;
43106f6ba60Sopenharmony_ci        pTmp = end;
43206f6ba60Sopenharmony_ci        if (++count >= cntVec) {
43306f6ba60Sopenharmony_ci            break;
43406f6ba60Sopenharmony_ci        }
43506f6ba60Sopenharmony_ci    }
43606f6ba60Sopenharmony_ci    bootTime = bootTime * (uint64_t)GetUserHz();
43706f6ba60Sopenharmony_ci    return count;
43806f6ba60Sopenharmony_ci}
43906f6ba60Sopenharmony_ci
44006f6ba60Sopenharmony_cibool ProcessDataPlugin::ReadCpuUsage(int pid, uint64_t& cpuTime)
44106f6ba60Sopenharmony_ci{
44206f6ba60Sopenharmony_ci    std::string path = path_ + std::to_string(pid) + "/stat";
44306f6ba60Sopenharmony_ci    std::ifstream input(path, std::ios::in);
44406f6ba60Sopenharmony_ci    CHECK_TRUE(!input.fail(), false, "%s open %s failed, errno = %d", __func__, path.c_str(), errno);
44506f6ba60Sopenharmony_ci    do {
44606f6ba60Sopenharmony_ci        if (!input.good()) {
44706f6ba60Sopenharmony_ci            return false;
44806f6ba60Sopenharmony_ci        }
44906f6ba60Sopenharmony_ci        std::string line;
45006f6ba60Sopenharmony_ci        getline(input, line);
45106f6ba60Sopenharmony_ci        line += '\n';
45206f6ba60Sopenharmony_ci        GetCpuUsageData(line, cpuTime);
45306f6ba60Sopenharmony_ci    } while (0);
45406f6ba60Sopenharmony_ci    input.close();
45506f6ba60Sopenharmony_ci
45606f6ba60Sopenharmony_ci    return true;
45706f6ba60Sopenharmony_ci}
45806f6ba60Sopenharmony_ci
45906f6ba60Sopenharmony_ciuint32_t ProcessDataPlugin::GetCpuUsageData(const std::string& line, uint64_t& cpuTime)
46006f6ba60Sopenharmony_ci{
46106f6ba60Sopenharmony_ci    uint64_t num;
46206f6ba60Sopenharmony_ci    uint32_t count = 0;
46306f6ba60Sopenharmony_ci    char* end = nullptr;
46406f6ba60Sopenharmony_ci    char* pTmp = const_cast<char*>(line.c_str());
46506f6ba60Sopenharmony_ci    int i = 0;
46606f6ba60Sopenharmony_ci    constexpr uint32_t cntVec = 4;
46706f6ba60Sopenharmony_ci
46806f6ba60Sopenharmony_ci    while (FindFirstSpace(&pTmp)) {
46906f6ba60Sopenharmony_ci        pTmp++;
47006f6ba60Sopenharmony_ci        if (++i >= STAT_COUNT) {
47106f6ba60Sopenharmony_ci            break;
47206f6ba60Sopenharmony_ci        }
47306f6ba60Sopenharmony_ci    }
47406f6ba60Sopenharmony_ci    std::vector<uint64_t> cpuUsageVec;
47506f6ba60Sopenharmony_ci    cpuTime = 0;
47606f6ba60Sopenharmony_ci    while (pTmp != nullptr && *pTmp != '\n') {
47706f6ba60Sopenharmony_ci        CHECK_TRUE(FindFirstNum(&pTmp), count, "%s: FindFirstNum failed", __func__);
47806f6ba60Sopenharmony_ci        num = strtoull(pTmp, &end, DEC_BASE);
47906f6ba60Sopenharmony_ci        cpuUsageVec.push_back(num);
48006f6ba60Sopenharmony_ci        cpuTime += num;
48106f6ba60Sopenharmony_ci        pTmp = end;
48206f6ba60Sopenharmony_ci        if (++count >= cntVec) {
48306f6ba60Sopenharmony_ci            break;
48406f6ba60Sopenharmony_ci        }
48506f6ba60Sopenharmony_ci    }
48606f6ba60Sopenharmony_ci    cpuTime = cpuTime * (uint64_t)GetUserHz();
48706f6ba60Sopenharmony_ci    return count;
48806f6ba60Sopenharmony_ci}
48906f6ba60Sopenharmony_ci
49006f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteDiskioData(int pid, T& processinfo)
49106f6ba60Sopenharmony_ci{
49206f6ba60Sopenharmony_ci    std::string path = path_ + std::to_string(pid) + "/io";
49306f6ba60Sopenharmony_ci    std::ifstream input(path, std::ios::in);
49406f6ba60Sopenharmony_ci    if (input.fail()) {
49506f6ba60Sopenharmony_ci        return false;
49606f6ba60Sopenharmony_ci    }
49706f6ba60Sopenharmony_ci
49806f6ba60Sopenharmony_ci    auto* diskInfo = processinfo.mutable_diskinfo();
49906f6ba60Sopenharmony_ci    do {
50006f6ba60Sopenharmony_ci        if (!input.good()) {
50106f6ba60Sopenharmony_ci            return false;
50206f6ba60Sopenharmony_ci        }
50306f6ba60Sopenharmony_ci        std::string line;
50406f6ba60Sopenharmony_ci        getline(input, line);
50506f6ba60Sopenharmony_ci        line += '\n';
50606f6ba60Sopenharmony_ci        GetDiskioData(line, *diskInfo);
50706f6ba60Sopenharmony_ci    } while (!input.eof());
50806f6ba60Sopenharmony_ci    input.close();
50906f6ba60Sopenharmony_ci
51006f6ba60Sopenharmony_ci    return true;
51106f6ba60Sopenharmony_ci}
51206f6ba60Sopenharmony_ci
51306f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::GetDiskioData(std::string& line, T& diskioInfo)
51406f6ba60Sopenharmony_ci{
51506f6ba60Sopenharmony_ci    char* pTmp = const_cast<char*>(line.c_str());
51606f6ba60Sopenharmony_ci    CHECK_NOTNULL(pTmp, false, "param invalid!");
51706f6ba60Sopenharmony_ci
51806f6ba60Sopenharmony_ci    uint64_t num;
51906f6ba60Sopenharmony_ci    if (!std::strncmp(pTmp, "rchar:", strlen("rchar:"))) {
52006f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get rchar failed", __func__);
52106f6ba60Sopenharmony_ci        diskioInfo.set_rchar(num);
52206f6ba60Sopenharmony_ci    } else if (!std::strncmp(pTmp, "wchar:", strlen("wchar:"))) {
52306f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get wchar failed", __func__);
52406f6ba60Sopenharmony_ci        diskioInfo.set_wchar(num);
52506f6ba60Sopenharmony_ci    } else if (!std::strncmp(pTmp, "syscr:", strlen("syscr:"))) {
52606f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get syscr failed", __func__);
52706f6ba60Sopenharmony_ci        diskioInfo.set_syscr(num);
52806f6ba60Sopenharmony_ci    } else if (!std::strncmp(pTmp, "syscw:", strlen("syscw:"))) {
52906f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get syscw failed", __func__);
53006f6ba60Sopenharmony_ci        diskioInfo.set_syscw(num);
53106f6ba60Sopenharmony_ci    } else if (!std::strncmp(pTmp, "read_bytes:", strlen("read_bytes:"))) {
53206f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get read_bytes failed", __func__);
53306f6ba60Sopenharmony_ci        diskioInfo.set_rbytes(num);
53406f6ba60Sopenharmony_ci    } else if (!std::strncmp(pTmp, "write_bytes:", strlen("write_bytes:"))) {
53506f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get write_bytes failed", __func__);
53606f6ba60Sopenharmony_ci        diskioInfo.set_wbytes(num);
53706f6ba60Sopenharmony_ci    } else if (!std::strncmp(pTmp, "cancelled_write_bytes:", strlen("cancelled_write_bytes:"))) {
53806f6ba60Sopenharmony_ci        CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get cancelled_write_bytes failed", __func__);
53906f6ba60Sopenharmony_ci        diskioInfo.set_cancelled_wbytes(num);
54006f6ba60Sopenharmony_ci    }
54106f6ba60Sopenharmony_ci
54206f6ba60Sopenharmony_ci    return true;
54306f6ba60Sopenharmony_ci}
54406f6ba60Sopenharmony_ci
54506f6ba60Sopenharmony_cibool ProcessDataPlugin::FindFirstSpace(char** p)
54606f6ba60Sopenharmony_ci{
54706f6ba60Sopenharmony_ci    CHECK_NOTNULL(*p, false, "ProcessDataPlugin:%s", __func__);
54806f6ba60Sopenharmony_ci    while (**p != ' ') {
54906f6ba60Sopenharmony_ci        if (**p == '\0' || **p == '\n') {
55006f6ba60Sopenharmony_ci            return false;
55106f6ba60Sopenharmony_ci        }
55206f6ba60Sopenharmony_ci        (*p)++;
55306f6ba60Sopenharmony_ci    }
55406f6ba60Sopenharmony_ci    return true;
55506f6ba60Sopenharmony_ci}
55606f6ba60Sopenharmony_ci
55706f6ba60Sopenharmony_cibool ProcessDataPlugin::FindFirstNum(char** p)
55806f6ba60Sopenharmony_ci{
55906f6ba60Sopenharmony_ci    CHECK_NOTNULL(*p, false, "ProcessDataPlugin:%s", __func__);
56006f6ba60Sopenharmony_ci    while (**p > '9' || **p < '0') {
56106f6ba60Sopenharmony_ci        if (**p == '\0' || **p == '\n') {
56206f6ba60Sopenharmony_ci            return false;
56306f6ba60Sopenharmony_ci        }
56406f6ba60Sopenharmony_ci        (*p)++;
56506f6ba60Sopenharmony_ci    }
56606f6ba60Sopenharmony_ci    return true;
56706f6ba60Sopenharmony_ci}
56806f6ba60Sopenharmony_ci
56906f6ba60Sopenharmony_cibool ProcessDataPlugin::GetValidValue(char* p, uint64_t& num)
57006f6ba60Sopenharmony_ci{
57106f6ba60Sopenharmony_ci    char* end = nullptr;
57206f6ba60Sopenharmony_ci    CHECK_TRUE(FindFirstNum(&p), false, "%s: FindFirstNum failed", __func__);
57306f6ba60Sopenharmony_ci    num = strtoull(p, &end, DEC_BASE);
57406f6ba60Sopenharmony_ci    CHECK_TRUE(num >= 0, false, "%s:strtoull failed", __func__);
57506f6ba60Sopenharmony_ci    return true;
57606f6ba60Sopenharmony_ci}
57706f6ba60Sopenharmony_ci
57806f6ba60Sopenharmony_ci// read /proc/pid/smaps_rollup
57906f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WritePssData(int pid, T& processInfo)
58006f6ba60Sopenharmony_ci{
58106f6ba60Sopenharmony_ci    std::string path = path_ + std::to_string(pid) + "/smaps_rollup";
58206f6ba60Sopenharmony_ci    std::ifstream input(path, std::ios::in);
58306f6ba60Sopenharmony_ci
58406f6ba60Sopenharmony_ci    // Not capturing ENOENT (file does not exist) errors, it is common for node smaps_rollup files to be unreadable.
58506f6ba60Sopenharmony_ci    CHECK_TRUE(!input.fail(), false, "%s open %s failed, errno = %d", __func__, path.c_str(), errno);
58606f6ba60Sopenharmony_ci
58706f6ba60Sopenharmony_ci    auto* pssInfo = processInfo.mutable_pssinfo();
58806f6ba60Sopenharmony_ci    do {
58906f6ba60Sopenharmony_ci        if (!input.good()) {
59006f6ba60Sopenharmony_ci            return false;
59106f6ba60Sopenharmony_ci        }
59206f6ba60Sopenharmony_ci        std::string line;
59306f6ba60Sopenharmony_ci        getline(input, line);
59406f6ba60Sopenharmony_ci        line += '\n';
59506f6ba60Sopenharmony_ci        std::string::size_type pos = 0u;
59606f6ba60Sopenharmony_ci        if (line.find("Pss:", pos) != std::string::npos) {
59706f6ba60Sopenharmony_ci            char* pTmp = const_cast<char*>(line.c_str());
59806f6ba60Sopenharmony_ci            uint64_t num;
59906f6ba60Sopenharmony_ci            CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: FindFirstNum failed", __func__);
60006f6ba60Sopenharmony_ci            pssInfo->set_pss_info(num);
60106f6ba60Sopenharmony_ci            return true;
60206f6ba60Sopenharmony_ci        }
60306f6ba60Sopenharmony_ci    } while (!input.eof());
60406f6ba60Sopenharmony_ci    input.close();
60506f6ba60Sopenharmony_ci
60606f6ba60Sopenharmony_ci    return false;
60706f6ba60Sopenharmony_ci}
608