1e509ee18Sopenharmony_ci/*
2e509ee18Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3e509ee18Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e509ee18Sopenharmony_ci * you may not use this file except in compliance with the License.
5e509ee18Sopenharmony_ci * You may obtain a copy of the License at
6e509ee18Sopenharmony_ci *
7e509ee18Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e509ee18Sopenharmony_ci *
9e509ee18Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e509ee18Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e509ee18Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e509ee18Sopenharmony_ci * See the License for the specific language governing permissions and
13e509ee18Sopenharmony_ci * limitations under the License.
14e509ee18Sopenharmony_ci */
15e509ee18Sopenharmony_ci
16e509ee18Sopenharmony_ci#include "tooling/client/domain/profiler_client.h"
17e509ee18Sopenharmony_ci#include "tooling/base/pt_types.h"
18e509ee18Sopenharmony_ci#include "common/log_wrapper.h"
19e509ee18Sopenharmony_ci#include "tooling/utils/utils.h"
20e509ee18Sopenharmony_ci#include "tooling/client/session/session.h"
21e509ee18Sopenharmony_ci
22e509ee18Sopenharmony_ci#include <map>
23e509ee18Sopenharmony_ci#include <functional>
24e509ee18Sopenharmony_ci#include <cstring>
25e509ee18Sopenharmony_ci#include <fstream>
26e509ee18Sopenharmony_ci
27e509ee18Sopenharmony_ciusing Result = panda::ecmascript::tooling::Result;
28e509ee18Sopenharmony_ciusing Profile = panda::ecmascript::tooling::Profile;
29e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain {
30e509ee18Sopenharmony_cibool ProfilerClient::DispatcherCmd(const std::string &cmd)
31e509ee18Sopenharmony_ci{
32e509ee18Sopenharmony_ci    std::map<std::string, std::function<int()>> dispatcherTable {
33e509ee18Sopenharmony_ci        { "cpuprofile", std::bind(&ProfilerClient::CpuprofileCommand, this)},
34e509ee18Sopenharmony_ci        { "cpuprofile-stop", std::bind(&ProfilerClient::CpuprofileStopCommand, this)},
35e509ee18Sopenharmony_ci        { "cpuprofile-setSamplingInterval", std::bind(&ProfilerClient::SetSamplingIntervalCommand, this)},
36e509ee18Sopenharmony_ci        { "cpuprofile-enable", std::bind(&ProfilerClient::CpuprofileEnableCommand, this)},
37e509ee18Sopenharmony_ci        { "cpuprofile-disable", std::bind(&ProfilerClient::CpuprofileDisableCommand, this)},
38e509ee18Sopenharmony_ci    };
39e509ee18Sopenharmony_ci
40e509ee18Sopenharmony_ci    auto entry = dispatcherTable.find(cmd);
41e509ee18Sopenharmony_ci    if (entry == dispatcherTable.end()) {
42e509ee18Sopenharmony_ci        LOGI("Unknown commond: %{public}s", cmd.c_str());
43e509ee18Sopenharmony_ci        return false;
44e509ee18Sopenharmony_ci    }
45e509ee18Sopenharmony_ci    entry->second();
46e509ee18Sopenharmony_ci    LOGI("DispatcherCmd cmd: %{public}s", cmd.c_str());
47e509ee18Sopenharmony_ci    return true;
48e509ee18Sopenharmony_ci}
49e509ee18Sopenharmony_ci
50e509ee18Sopenharmony_ciint ProfilerClient::CpuprofileEnableCommand()
51e509ee18Sopenharmony_ci{
52e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
53e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
54e509ee18Sopenharmony_ci
55e509ee18Sopenharmony_ci    idEventMap_.emplace(id, "cpuprofileenable");
56e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
57e509ee18Sopenharmony_ci    request->Add("id", id);
58e509ee18Sopenharmony_ci    request->Add("method", "Profiler.enable");
59e509ee18Sopenharmony_ci
60e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
61e509ee18Sopenharmony_ci    request->Add("params", params);
62e509ee18Sopenharmony_ci
63e509ee18Sopenharmony_ci    std::string message = request->Stringify();
64e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
65e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Profiler");
66e509ee18Sopenharmony_ci    }
67e509ee18Sopenharmony_ci    return 0;
68e509ee18Sopenharmony_ci}
69e509ee18Sopenharmony_ci
70e509ee18Sopenharmony_ciint ProfilerClient::CpuprofileDisableCommand()
71e509ee18Sopenharmony_ci{
72e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
73e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
74e509ee18Sopenharmony_ci
75e509ee18Sopenharmony_ci    idEventMap_.emplace(id, "cpuprofiledisable");
76e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
77e509ee18Sopenharmony_ci    request->Add("id", id);
78e509ee18Sopenharmony_ci    request->Add("method", "Profiler.disable");
79e509ee18Sopenharmony_ci
80e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
81e509ee18Sopenharmony_ci    request->Add("params", params);
82e509ee18Sopenharmony_ci
83e509ee18Sopenharmony_ci    std::string message = request->Stringify();
84e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
85e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Profiler");
86e509ee18Sopenharmony_ci    }
87e509ee18Sopenharmony_ci    return 0;
88e509ee18Sopenharmony_ci}
89e509ee18Sopenharmony_ci
90e509ee18Sopenharmony_ciint ProfilerClient::CpuprofileCommand()
91e509ee18Sopenharmony_ci{
92e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
93e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
94e509ee18Sopenharmony_ci
95e509ee18Sopenharmony_ci    idEventMap_.emplace(id, "cpuprofile");
96e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
97e509ee18Sopenharmony_ci    request->Add("id", id);
98e509ee18Sopenharmony_ci    request->Add("method", "Profiler.start");
99e509ee18Sopenharmony_ci
100e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
101e509ee18Sopenharmony_ci    request->Add("params", params);
102e509ee18Sopenharmony_ci
103e509ee18Sopenharmony_ci    std::string message = request->Stringify();
104e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
105e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Profiler");
106e509ee18Sopenharmony_ci    }
107e509ee18Sopenharmony_ci    return 0;
108e509ee18Sopenharmony_ci}
109e509ee18Sopenharmony_ci
110e509ee18Sopenharmony_ciint ProfilerClient::CpuprofileStopCommand()
111e509ee18Sopenharmony_ci{
112e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
113e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
114e509ee18Sopenharmony_ci
115e509ee18Sopenharmony_ci    idEventMap_.emplace(id, "cpuprofilestop");
116e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
117e509ee18Sopenharmony_ci    request->Add("id", id);
118e509ee18Sopenharmony_ci    request->Add("method", "Profiler.stop");
119e509ee18Sopenharmony_ci
120e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
121e509ee18Sopenharmony_ci    request->Add("params", params);
122e509ee18Sopenharmony_ci
123e509ee18Sopenharmony_ci    std::string message = request->Stringify();
124e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
125e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Profiler");
126e509ee18Sopenharmony_ci    }
127e509ee18Sopenharmony_ci    return 0;
128e509ee18Sopenharmony_ci}
129e509ee18Sopenharmony_ci
130e509ee18Sopenharmony_ciint ProfilerClient::SetSamplingIntervalCommand()
131e509ee18Sopenharmony_ci{
132e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
133e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
134e509ee18Sopenharmony_ci
135e509ee18Sopenharmony_ci    idEventMap_.emplace(id, "setsamplinginterval");
136e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
137e509ee18Sopenharmony_ci    request->Add("id", id);
138e509ee18Sopenharmony_ci    request->Add("method", "Profiler.setSamplingInterval");
139e509ee18Sopenharmony_ci
140e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
141e509ee18Sopenharmony_ci    params->Add("interval", interval_);
142e509ee18Sopenharmony_ci    request->Add("params", params);
143e509ee18Sopenharmony_ci
144e509ee18Sopenharmony_ci    std::string message = request->Stringify();
145e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
146e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Profiler");
147e509ee18Sopenharmony_ci    }
148e509ee18Sopenharmony_ci    return 0;
149e509ee18Sopenharmony_ci}
150e509ee18Sopenharmony_ci
151e509ee18Sopenharmony_civoid ProfilerClient::RecvProfilerResult(std::unique_ptr<PtJson> json)
152e509ee18Sopenharmony_ci{
153e509ee18Sopenharmony_ci    if (json == nullptr) {
154e509ee18Sopenharmony_ci        LOGE("arkdb: json parse error");
155e509ee18Sopenharmony_ci        return;
156e509ee18Sopenharmony_ci    }
157e509ee18Sopenharmony_ci
158e509ee18Sopenharmony_ci    if (!json->IsObject()) {
159e509ee18Sopenharmony_ci        LOGE("arkdb: json parse format error");
160e509ee18Sopenharmony_ci        json->ReleaseRoot();
161e509ee18Sopenharmony_ci        return;
162e509ee18Sopenharmony_ci    }
163e509ee18Sopenharmony_ci
164e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> result;
165e509ee18Sopenharmony_ci    Result ret = json->GetObject("result", &result);
166e509ee18Sopenharmony_ci    if (ret != Result::SUCCESS) {
167e509ee18Sopenharmony_ci        LOGE("arkdb: find result error");
168e509ee18Sopenharmony_ci        return;
169e509ee18Sopenharmony_ci    }
170e509ee18Sopenharmony_ci
171e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> profile;
172e509ee18Sopenharmony_ci    ret = result->GetObject("profile", &profile);
173e509ee18Sopenharmony_ci    if (ret != Result::SUCCESS) {
174e509ee18Sopenharmony_ci        LOGE("arkdb: the cmd is not cp-stop!");
175e509ee18Sopenharmony_ci        return;
176e509ee18Sopenharmony_ci    }
177e509ee18Sopenharmony_ci
178e509ee18Sopenharmony_ci    char date[16];
179e509ee18Sopenharmony_ci    char time[16];
180e509ee18Sopenharmony_ci    bool res = Utils::GetCurrentTime(date, time, sizeof(date));
181e509ee18Sopenharmony_ci    if (!res) {
182e509ee18Sopenharmony_ci        LOGE("arkdb: get time failed");
183e509ee18Sopenharmony_ci        return;
184e509ee18Sopenharmony_ci    }
185e509ee18Sopenharmony_ci
186e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
187e509ee18Sopenharmony_ci    ProfilerSingleton &pro = session->GetProfilerSingleton();
188e509ee18Sopenharmony_ci    std::string fileName = "CPU-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" +
189e509ee18Sopenharmony_ci                           std::string(time) + ".cpuprofile";
190e509ee18Sopenharmony_ci    std::string cpufile = pro.GetAddress() + fileName;
191e509ee18Sopenharmony_ci    std::cout << "session " << sessionId_ << " cpuprofile file name is " << cpufile << std::endl;
192e509ee18Sopenharmony_ci    std::cout << ">>> ";
193e509ee18Sopenharmony_ci    fflush(stdout);
194e509ee18Sopenharmony_ci    WriteCpuProfileForFile(cpufile, profile->Stringify());
195e509ee18Sopenharmony_ci    pro.AddCpuName(fileName);
196e509ee18Sopenharmony_ci}
197e509ee18Sopenharmony_ci
198e509ee18Sopenharmony_cibool ProfilerClient::WriteCpuProfileForFile(const std::string &fileName, const std::string &data)
199e509ee18Sopenharmony_ci{
200e509ee18Sopenharmony_ci    std::ofstream ofs;
201e509ee18Sopenharmony_ci    std::string realPath;
202e509ee18Sopenharmony_ci    bool res = Utils::RealPath(fileName, realPath, false);
203e509ee18Sopenharmony_ci    if (!res) {
204e509ee18Sopenharmony_ci        LOGE("arkdb: path is not realpath!");
205e509ee18Sopenharmony_ci        return false;
206e509ee18Sopenharmony_ci    }
207e509ee18Sopenharmony_ci    ofs.open(fileName.c_str(), std::ios::out);
208e509ee18Sopenharmony_ci    if (!ofs.is_open()) {
209e509ee18Sopenharmony_ci        LOGE("arkdb: file open error!");
210e509ee18Sopenharmony_ci        return false;
211e509ee18Sopenharmony_ci    }
212e509ee18Sopenharmony_ci    size_t strSize = data.size();
213e509ee18Sopenharmony_ci    ofs.write(data.c_str(), strSize);
214e509ee18Sopenharmony_ci    ofs.close();
215e509ee18Sopenharmony_ci    ofs.clear();
216e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
217e509ee18Sopenharmony_ci    ProfilerSingleton &pro = session->GetProfilerSingleton();
218e509ee18Sopenharmony_ci    pro.SetAddress("/data/");
219e509ee18Sopenharmony_ci    return true;
220e509ee18Sopenharmony_ci}
221e509ee18Sopenharmony_ci
222e509ee18Sopenharmony_civoid ProfilerClient::SetSamplingInterval(int interval)
223e509ee18Sopenharmony_ci{
224e509ee18Sopenharmony_ci    this->interval_ = interval;
225e509ee18Sopenharmony_ci}
226e509ee18Sopenharmony_ci} // OHOS::ArkCompiler::Toolchain
227