From 281e6a9c65e54ccebf643f8117ea748656d941f9 Mon Sep 17 00:00:00 2001 From: yanpeng Date: Tue, 24 Oct 2023 15:56:55 +0800 Subject: [PATCH 1/3] client support multi-sessions Signed-off-by: yanpeng --- tooling/client/BUILD.gn | 1 + tooling/client/ark_cli/main.cpp | 113 +++------ tooling/client/domain/debugger_client.cpp | 224 ++++++++++++------ tooling/client/domain/debugger_client.h | 53 +++-- tooling/client/domain/heapprofiler_client.cpp | 129 +++++++--- tooling/client/domain/heapprofiler_client.h | 21 +- tooling/client/domain/profiler_client.cpp | 95 +++++--- tooling/client/domain/profiler_client.h | 19 +- tooling/client/domain/runtime_client.cpp | 102 ++++++-- tooling/client/domain/runtime_client.h | 17 +- tooling/client/domain/test_client.cpp | 37 ++- tooling/client/manager/breakpoint_manager.cpp | 7 +- tooling/client/manager/breakpoint_manager.h | 5 +- tooling/client/manager/domain_manager.cpp | 7 + tooling/client/manager/domain_manager.h | 3 +- tooling/client/manager/message_manager.h | 70 ++++++ tooling/client/manager/stack_manager.cpp | 7 +- tooling/client/manager/stack_manager.h | 5 +- tooling/client/manager/variable_manager.cpp | 6 - tooling/client/manager/variable_manager.h | 5 +- tooling/client/session/session.cpp | 190 +++++++++++++++ tooling/client/session/session.h | 159 +++++++++++++ tooling/client/utils/cli_command.cpp | 156 +++++++----- tooling/client/utils/cli_command.h | 18 +- tooling/client/utils/utils.cpp | 11 + tooling/client/utils/utils.h | 1 + tooling/client/websocket/websocket_client.cpp | 22 +- tooling/client/websocket/websocket_client.h | 3 +- 28 files changed, 1074 insertions(+), 412 deletions(-) create mode 100755 tooling/client/manager/message_manager.h create mode 100755 tooling/client/session/session.cpp create mode 100755 tooling/client/session/session.h diff --git a/tooling/client/BUILD.gn b/tooling/client/BUILD.gn index ba992144..e87bfff8 100644 --- a/tooling/client/BUILD.gn +++ b/tooling/client/BUILD.gn @@ -38,6 +38,7 @@ ohos_source_set("libark_client_set") { "manager/domain_manager.cpp", "manager/stack_manager.cpp", "manager/variable_manager.cpp", + "session/session.cpp", "utils/cli_command.cpp", "utils/utils.cpp", "websocket/websocket_client.cpp", diff --git a/tooling/client/ark_cli/main.cpp b/tooling/client/ark_cli/main.cpp index f3b7df10..d78b4f44 100644 --- a/tooling/client/ark_cli/main.cpp +++ b/tooling/client/ark_cli/main.cpp @@ -22,28 +22,14 @@ #include #include "tooling/client/utils/cli_command.h" +#include "session/session.h" +#include "manager/message_manager.h" namespace OHOS::ArkCompiler::Toolchain { -uint32_t g_messageId = 0; -uv_async_t* g_socketSignal; uv_async_t* g_inputSignal; uv_async_t* g_releaseHandle; uv_loop_t* g_loop; -DomainManager g_domainManager; -WebsocketClient g_cliSocket; - -bool StrToUInt(const char *content, uint32_t *result) -{ - const int dec = 10; - char *endPtr = nullptr; - *result = std::strtoul(content, &endPtr, dec); - if (endPtr == content || *endPtr != '\0') { - return false; - } - return true; -} - void ReleaseHandle([[maybe_unused]] uv_async_t *releaseHandle) { uv_close(reinterpret_cast(g_inputSignal), [](uv_handle_t* handle) { @@ -72,21 +58,36 @@ void ReleaseHandle([[maybe_unused]] uv_async_t *releaseHandle) } } +void InputMessageInSession(uint32_t sessionId, std::vector& cliCmdStr) +{ + CliCommand cmd(cliCmdStr, sessionId); + cmd.ExecCommand(); + return; +} + void InputOnMessage(uv_async_t *handle) { char* msg = static_cast(handle->data); std::string inputStr = std::string(msg); + if (msg != nullptr) { + free(msg); + } std::vector cliCmdStr = Utils::SplitString(inputStr, " "); - g_messageId += 1; - CliCommand cmd(cliCmdStr, g_messageId, g_domainManager, g_cliSocket); - if (cmd.ExecCommand() == ErrCode::ERR_FAIL) { - g_messageId -= 1; + if (cliCmdStr[0] == "forall") { + if (strstr(cliCmdStr[1].c_str(), "session") != nullptr) { + std::cout << "command " << cliCmdStr[1] << " not support forall" << std::endl; + } else { + cliCmdStr.erase(cliCmdStr.begin()); + SessionManager::getInstance().CmdForAllSessions(std::bind(InputMessageInSession, std::placeholders::_1, + cliCmdStr)); + } + } else { + uint32_t sessionId = SessionManager::getInstance().GetCurrentSessionId(); + InputMessageInSession(sessionId, cliCmdStr); } + std::cout << ">>> "; fflush(stdout); - if (msg != nullptr) { - free(msg); - } } void GetInputCommand([[maybe_unused]] void *arg) @@ -100,7 +101,6 @@ void GetInputCommand([[maybe_unused]] void *arg) } if ((!strcmp(inputStr.c_str(), "quit")) || (!strcmp(inputStr.c_str(), "q"))) { LOGE("arkdb: quit"); - g_cliSocket.Close(); if (uv_is_active(reinterpret_cast(g_releaseHandle))) { uv_async_send(g_releaseHandle); } @@ -111,7 +111,6 @@ void GetInputCommand([[maybe_unused]] void *arg) char* msg = (char*)malloc(len + 1); if ((msg != nullptr) && uv_is_active(reinterpret_cast(g_inputSignal))) { if (strncpy_s(msg, len + 1, inputStr.c_str(), len) != 0) { - g_cliSocket.Close(); if (uv_is_active(reinterpret_cast(g_releaseHandle))) { uv_async_send(g_releaseHandle); } @@ -124,69 +123,30 @@ void GetInputCommand([[maybe_unused]] void *arg) } } -void SocketOnMessage(uv_async_t *handle) -{ - char* msg = static_cast(handle->data); - g_domainManager.DispatcherReply(msg); - if (msg != nullptr) { - free(msg); - } -} - -void GetSocketMessage([[maybe_unused]] void *arg) +void SocketOnMessage([[maybe_unused]] uv_async_t *handle) { - while (g_cliSocket.IsConnected()) { - std::string decMessage = g_cliSocket.Decode(); - uint32_t len = decMessage.length(); - if (len == 0) { + uint32_t sessionId = 0; + std::string message; + while (MessageManager::getInstance().MessagePop(sessionId, message)) { + Session* session = SessionManager::getInstance().GetSessionById(sessionId); + if (session == nullptr) { + LOGE("arkdb get session by id %{public}u failed", sessionId); continue; } - char* msg = (char*)malloc(len + 1); - if ((msg != nullptr) && uv_is_active(reinterpret_cast(g_socketSignal))) { - if (strncpy_s(msg, len + 1, decMessage.c_str(), len) != 0) { - g_cliSocket.Close(); - if (uv_is_active(reinterpret_cast(g_releaseHandle))) { - uv_async_send(g_releaseHandle); - } - break; - } - g_socketSignal->data = std::move(msg); - uv_async_send(g_socketSignal); - } + + session->ProcSocketMsg(const_cast(message.c_str())); } } int Main(const int argc, const char** argv) { - uint32_t port = 0; - if (argc < 2) { // 2: two parameters LOGE("arkdb is missing a parameter"); return -1; } if (strstr(argv[0], "arkdb") != nullptr) { - if (StrToUInt(argv[1], &port)) { - if ((port <= 0) || (port >= 65535)) { // 65535: max port - LOGE("arkdb:InitToolchainWebSocketForPort the port = %{public}d is wrong.", port); - return -1; - } - if (!g_cliSocket.InitToolchainWebSocketForPort(port, 5)) { // 5: five times - LOGE("arkdb:InitToolchainWebSocketForPort failed"); - return -1; - } - } else { - if (!g_cliSocket.InitToolchainWebSocketForSockName(argv[1])) { - LOGE("arkdb:InitToolchainWebSocketForSockName failed"); - return -1; - } - } - - if (!g_cliSocket.ClientSendWSUpgradeReq()) { - LOGE("arkdb:ClientSendWSUpgradeReq failed"); - return -1; - } - if (!g_cliSocket.ClientRecvWSUpgradeRsp()) { - LOGE("arkdb:ClientRecvWSUpgradeRsp failed"); + if (SessionManager::getInstance().CreateDefaultSession(argv[1])) { + LOGE("arkdb create default session failed"); return -1; } @@ -204,9 +164,6 @@ int Main(const int argc, const char** argv) uv_thread_t inputTid; uv_thread_create(&inputTid, GetInputCommand, nullptr); - uv_thread_t socketTid; - uv_thread_create(&socketTid, GetSocketMessage, nullptr); - uv_run(g_loop, UV_RUN_DEFAULT); } return 0; diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp index cfb9eefb..fc4af54c 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -21,53 +21,56 @@ #include "tooling/client/manager/breakpoint_manager.h" #include "tooling/client/manager/stack_manager.h" #include "tooling/base/pt_json.h" +#include "session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { -bool DebuggerClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr) +bool DebuggerClient::DispatcherCmd(const std::string &cmd) { - std::map> dispatcherTable { - { "break", std::bind(&DebuggerClient::BreakCommand, this, id)}, - { "backtrack", std::bind(&DebuggerClient::BacktrackCommand, this, id)}, - { "continue", std::bind(&DebuggerClient::ResumeCommand, this, id)}, - { "delete", std::bind(&DebuggerClient::DeleteCommand, this, id)}, - { "jump", std::bind(&DebuggerClient::JumpCommand, this, id)}, - { "disable", std::bind(&DebuggerClient::DisableCommand, this, id)}, - { "display", std::bind(&DebuggerClient::DisplayCommand, this, id)}, - { "enable", std::bind(&DebuggerClient::EnableCommand, this, id)}, - { "finish", std::bind(&DebuggerClient::FinishCommand, this, id)}, - { "frame", std::bind(&DebuggerClient::FrameCommand, this, id)}, - { "ignore", std::bind(&DebuggerClient::IgnoreCommand, this, id)}, - { "infobreakpoints", std::bind(&DebuggerClient::InfobreakpointsCommand, this, id)}, - { "infosource", std::bind(&DebuggerClient::InfosourceCommand, this, id)}, - { "list", std::bind(&DebuggerClient::ListCommand, this, id)}, - { "next", std::bind(&DebuggerClient::NextCommand, this, id)}, - { "ptype", std::bind(&DebuggerClient::PtypeCommand, this, id)}, - { "run", std::bind(&DebuggerClient::RunCommand, this, id)}, - { "setvar", std::bind(&DebuggerClient::SetvarCommand, this, id)}, - { "step", std::bind(&DebuggerClient::StepCommand, this, id)}, - { "undisplay", std::bind(&DebuggerClient::UndisplayCommand, this, id)}, - { "watch", std::bind(&DebuggerClient::WatchCommand, this, id)}, - { "resume", std::bind(&DebuggerClient::ResumeCommand, this, id)}, - { "step-into", std::bind(&DebuggerClient::StepIntoCommand, this, id)}, - { "step-out", std::bind(&DebuggerClient::StepOutCommand, this, id)}, - { "step-over", std::bind(&DebuggerClient::StepOverCommand, this, id)}, + std::map> dispatcherTable { + { "break", std::bind(&DebuggerClient::BreakCommand, this)}, + { "backtrack", std::bind(&DebuggerClient::BacktrackCommand, this)}, + { "continue", std::bind(&DebuggerClient::ResumeCommand, this)}, + { "delete", std::bind(&DebuggerClient::DeleteCommand, this)}, + { "jump", std::bind(&DebuggerClient::JumpCommand, this)}, + { "disable", std::bind(&DebuggerClient::DisableCommand, this)}, + { "display", std::bind(&DebuggerClient::DisplayCommand, this)}, + { "enable", std::bind(&DebuggerClient::EnableCommand, this)}, + { "finish", std::bind(&DebuggerClient::FinishCommand, this)}, + { "frame", std::bind(&DebuggerClient::FrameCommand, this)}, + { "ignore", std::bind(&DebuggerClient::IgnoreCommand, this)}, + { "infobreakpoints", std::bind(&DebuggerClient::InfobreakpointsCommand, this)}, + { "infosource", std::bind(&DebuggerClient::InfosourceCommand, this)}, + { "list", std::bind(&DebuggerClient::ListCommand, this)}, + { "next", std::bind(&DebuggerClient::NextCommand, this)}, + { "ptype", std::bind(&DebuggerClient::PtypeCommand, this)}, + { "run", std::bind(&DebuggerClient::RunCommand, this)}, + { "setvar", std::bind(&DebuggerClient::SetvarCommand, this)}, + { "step", std::bind(&DebuggerClient::StepCommand, this)}, + { "undisplay", std::bind(&DebuggerClient::UndisplayCommand, this)}, + { "watch", std::bind(&DebuggerClient::WatchCommand, this)}, + { "resume", std::bind(&DebuggerClient::ResumeCommand, this)}, + { "step-into", std::bind(&DebuggerClient::StepIntoCommand, this)}, + { "step-out", std::bind(&DebuggerClient::StepOutCommand, this)}, + { "step-over", std::bind(&DebuggerClient::StepOverCommand, this)}, }; auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end()) { - *reqStr = entry->second(); + entry->second(); LOGI("DebuggerClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); return true; } - *reqStr = "Unknown commond: " + cmd; LOGI("DebuggerClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); return false; } -std::string DebuggerClient::BreakCommand(int id) +int DebuggerClient::BreakCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.setBreakpointByUrl"); @@ -77,16 +80,24 @@ std::string DebuggerClient::BreakCommand(int id) params->Add("lineNumber", breakPointInfoList_.back().lineNumber); params->Add("url", breakPointInfoList_.back().url.c_str()); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::BacktrackCommand([[maybe_unused]] int id) +int DebuggerClient::BacktrackCommand() { - return "backtrack"; + return 0; } -std::string DebuggerClient::DeleteCommand(int id) +int DebuggerClient::DeleteCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.removeBreakpoint"); @@ -95,148 +106,201 @@ std::string DebuggerClient::DeleteCommand(int id) std::string breakpointId = breakPointInfoList_.back().url; params->Add("breakpointId", breakpointId.c_str()); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::DisableCommand(int id) +int DebuggerClient::DisableCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.disable"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::DisplayCommand([[maybe_unused]] int id) +int DebuggerClient::DisplayCommand() { - return "display"; + return 0; } -std::string DebuggerClient::EnableCommand(int id) +int DebuggerClient::EnableCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.enable"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::FinishCommand([[maybe_unused]] int id) +int DebuggerClient::FinishCommand() { - return "finish"; + return 0; } -std::string DebuggerClient::FrameCommand([[maybe_unused]] int id) +int DebuggerClient::FrameCommand() { - return "frame"; + return 0; } -std::string DebuggerClient::IgnoreCommand([[maybe_unused]] int id) +int DebuggerClient::IgnoreCommand() { - return "ignore"; + return 0; } -std::string DebuggerClient::InfobreakpointsCommand([[maybe_unused]] int id) +int DebuggerClient::InfobreakpointsCommand() { - return "infobreakpoint"; + return 0; } -std::string DebuggerClient::InfosourceCommand([[maybe_unused]] int id) +int DebuggerClient::InfosourceCommand() { - return "infosource"; + return 0; } -std::string DebuggerClient::JumpCommand([[maybe_unused]] int id) +int DebuggerClient::JumpCommand() { - return "jump"; + return 0; } -std::string DebuggerClient::NextCommand([[maybe_unused]] int id) +int DebuggerClient::NextCommand() { - return "next"; + return 0; } -std::string DebuggerClient::ListCommand([[maybe_unused]] int id) +int DebuggerClient::ListCommand() { - return "list"; + return 0; } -std::string DebuggerClient::PtypeCommand([[maybe_unused]] int id) +int DebuggerClient::PtypeCommand() { - return "ptype"; + return 0; } -std::string DebuggerClient::RunCommand([[maybe_unused]] int id) +int DebuggerClient::RunCommand() { - return "run"; + return 0; } -std::string DebuggerClient::SetvarCommand([[maybe_unused]] int id) +int DebuggerClient::SetvarCommand() { - return "Debugger.setVariableValue"; + return 0; } -std::string DebuggerClient::StepCommand([[maybe_unused]] int id) +int DebuggerClient::StepCommand() { - return "step"; + return 0; } -std::string DebuggerClient::UndisplayCommand([[maybe_unused]] int id) +int DebuggerClient::UndisplayCommand() { - return "undisplay"; + return 0; } -std::string DebuggerClient::WatchCommand([[maybe_unused]] int id) +int DebuggerClient::WatchCommand() { - return "Debugger.evaluateOnCallFrame"; + return 0; } -std::string DebuggerClient::ResumeCommand(int id) +int DebuggerClient::ResumeCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.resume"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::StepIntoCommand(int id) +int DebuggerClient::StepIntoCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.stepInto"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::StepOutCommand(int id) +int DebuggerClient::StepOutCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.stepOut"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } -std::string DebuggerClient::StepOverCommand(int id) +int DebuggerClient::StepOverCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Debugger.stepOver"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return 0; } void DebuggerClient::AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber) @@ -290,7 +354,8 @@ void DebuggerClient::RecvReply(std::unique_ptr json) std::string breakpointId; ret = result->GetString("breakpointId", &breakpointId); if (ret == Result::SUCCESS) { - BreakPointManager &breakpoint = BreakPointManager::GetInstance(); + Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + BreakPointManager& breakpoint = session->GetBreakPointManager(); breakpoint.Createbreaklocation(std::move(json)); } } @@ -328,7 +393,8 @@ void DebuggerClient::PausedReply(const std::unique_ptr json) data.emplace(i + 1, std::move(callFrameInfo)); } - StackManager &stackManager = StackManager::GetInstance(); + Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + StackManager& stackManager = session->GetStackManager(); stackManager.ClearCallFrame(); stackManager.SetCallFrames(std::move(data)); } diff --git a/tooling/client/domain/debugger_client.h b/tooling/client/domain/debugger_client.h index 1864275e..204644b4 100644 --- a/tooling/client/domain/debugger_client.h +++ b/tooling/client/domain/debugger_client.h @@ -31,34 +31,34 @@ struct BreakPointInfo { }; class DebuggerClient final { public: - DebuggerClient() = default; + DebuggerClient(int32_t sessionId) : sessionId_(sessionId) {} ~DebuggerClient() = default; - bool DispatcherCmd(int id, const std::string &cmd, std::string* reqStr); - std::string BreakCommand(int id); - std::string BacktrackCommand(int id); - std::string DeleteCommand(int id); - std::string DisableCommand(int id); - std::string DisplayCommand(int id); - std::string EnableCommand(int id); - std::string FinishCommand(int id); - std::string FrameCommand(int id); - std::string IgnoreCommand(int id); - std::string InfobreakpointsCommand(int id); - std::string InfosourceCommand(int id); - std::string JumpCommand(int id); - std::string NextCommand(int id); - std::string ListCommand(int id); - std::string PtypeCommand(int id); - std::string RunCommand(int id); - std::string SetvarCommand(int id); - std::string StepCommand(int id); - std::string UndisplayCommand(int id); - std::string WatchCommand(int id); - std::string ResumeCommand(int id); - std::string StepIntoCommand(int id); - std::string StepOutCommand(int id); - std::string StepOverCommand(int id); + bool DispatcherCmd(const std::string &cmd); + int BreakCommand(); + int BacktrackCommand(); + int DeleteCommand(); + int DisableCommand(); + int DisplayCommand(); + int EnableCommand(); + int FinishCommand(); + int FrameCommand(); + int IgnoreCommand(); + int InfobreakpointsCommand(); + int InfosourceCommand(); + int JumpCommand(); + int NextCommand(); + int ListCommand(); + int PtypeCommand(); + int RunCommand(); + int SetvarCommand(); + int StepCommand(); + int UndisplayCommand(); + int WatchCommand(); + int ResumeCommand(); + int StepIntoCommand(); + int StepOutCommand(); + int StepOverCommand(); void AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber = 0); void RecvReply(std::unique_ptr json); @@ -66,6 +66,7 @@ public: private: std::vector breakPointInfoList_ {}; + int32_t sessionId_; }; } // OHOS::ArkCompiler::Toolchain #endif \ No newline at end of file diff --git a/tooling/client/domain/heapprofiler_client.cpp b/tooling/client/domain/heapprofiler_client.cpp index bde7a0da..09ad0375 100644 --- a/tooling/client/domain/heapprofiler_client.cpp +++ b/tooling/client/domain/heapprofiler_client.cpp @@ -16,6 +16,7 @@ #include "tooling/client/domain/heapprofiler_client.h" #include "common/log_wrapper.h" #include "tooling/client/utils/utils.h" +#include "session/session.h" #include #include @@ -24,38 +25,37 @@ using Result = panda::ecmascript::tooling::Result; namespace OHOS::ArkCompiler::Toolchain { static constexpr int32_t SAMPLING_INTERVAL = 16384; -bool HeapProfilerClient::DispatcherCmd(int id, const std::string &cmd, const std::string &arg, std::string* reqStr) +bool HeapProfilerClient::DispatcherCmd(const std::string &cmd, const std::string &arg) { - if (reqStr == nullptr) { - return false; - } path_ = arg; - std::map> dispatcherTable { - { "allocationtrack", std::bind(&HeapProfilerClient::AllocationTrackCommand, this, id)}, - { "allocationtrack-stop", std::bind(&HeapProfilerClient::AllocationTrackStopCommand, this, id)}, - { "heapdump", std::bind(&HeapProfilerClient::HeapDumpCommand, this, id)}, - { "heapprofiler-enable", std::bind(&HeapProfilerClient::Enable, this, id)}, - { "heapprofiler-disable", std::bind(&HeapProfilerClient::Disable, this, id)}, - { "sampling", std::bind(&HeapProfilerClient::Samping, this, id)}, - { "sampling-stop", std::bind(&HeapProfilerClient::SampingStop, this, id)}, - { "collectgarbage", std::bind(&HeapProfilerClient::CollectGarbage, this, id)} + std::map> dispatcherTable { + { "allocationtrack", std::bind(&HeapProfilerClient::AllocationTrackCommand, this)}, + { "allocationtrack-stop", std::bind(&HeapProfilerClient::AllocationTrackStopCommand, this)}, + { "heapdump", std::bind(&HeapProfilerClient::HeapDumpCommand, this)}, + { "heapprofiler-enable", std::bind(&HeapProfilerClient::Enable, this)}, + { "heapprofiler-disable", std::bind(&HeapProfilerClient::Disable, this)}, + { "sampling", std::bind(&HeapProfilerClient::Samping, this)}, + { "sampling-stop", std::bind(&HeapProfilerClient::SampingStop, this)}, + { "collectgarbage", std::bind(&HeapProfilerClient::CollectGarbage, this)} }; auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end() && entry->second != nullptr) { - *reqStr = entry->second(); + entry->second(); LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); return true; } - *reqStr = "Unknown commond: " + cmd; LOGI("DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); return false; } -std::string HeapProfilerClient::HeapDumpCommand(int id) +int HeapProfilerClient::HeapDumpCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, HEAPDUMP); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -66,11 +66,19 @@ std::string HeapProfilerClient::HeapDumpCommand(int id) params->Add("captureNumericValue", true); params->Add("exposeInternals", false); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::AllocationTrackCommand(int id) +int HeapProfilerClient::AllocationTrackCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, ALLOCATION); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -79,11 +87,19 @@ std::string HeapProfilerClient::AllocationTrackCommand(int id) std::unique_ptr params = PtJson::CreateObject(); params->Add("trackAllocations", true); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::AllocationTrackStopCommand(int id) +int HeapProfilerClient::AllocationTrackStopCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, ALLOCATION_STOP); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -92,11 +108,19 @@ std::string HeapProfilerClient::AllocationTrackStopCommand(int id) std::unique_ptr params = PtJson::CreateObject(); params->Add("reportProgress", true); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::Enable(int id) +int HeapProfilerClient::Enable() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, ENABLE); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -104,11 +128,19 @@ std::string HeapProfilerClient::Enable(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::Disable(int id) +int HeapProfilerClient::Disable() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, DISABLE); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -116,11 +148,19 @@ std::string HeapProfilerClient::Disable(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::Samping(int id) +int HeapProfilerClient::Samping() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, SAMPLING); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -129,11 +169,19 @@ std::string HeapProfilerClient::Samping(int id) std::unique_ptr params = PtJson::CreateObject(); params->Add("samplingInterval", SAMPLING_INTERVAL); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::SampingStop(int id) +int HeapProfilerClient::SampingStop() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, SAMPLING_STOP); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -141,11 +189,19 @@ std::string HeapProfilerClient::SampingStop(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } -std::string HeapProfilerClient::CollectGarbage(int id) +int HeapProfilerClient::CollectGarbage() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, COLLECT_GARBAGE); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -153,7 +209,12 @@ std::string HeapProfilerClient::CollectGarbage(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "HeapProfiler"); + } + return 0; } void HeapProfilerClient::RecvReply(std::unique_ptr json) @@ -213,10 +274,12 @@ void HeapProfilerClient::RecvReply(std::unique_ptr json) return; } if (isAllocationMsg_) { - fileName_ = "Heap-" + std::string(date) + "T" + std::string(time) + ".heaptimeline"; + fileName_ = "Heap-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" + std::string(time) + + ".heaptimeline"; std::cout << "heaptimeline file name is " << fileName_ << std::endl; } else { - fileName_ = "Heap-" + std::string(date) + "T" + std::string(time) + ".heapsnapshot"; + fileName_ = "Heap-"+ std::to_string(sessionId_) + "-" + std::string(date) + "T" + std::string(time) + + ".heapsnapshot"; std::cout << "heapsnapshot file name is " << fileName_ << std::endl; } std::cout << ">>> "; diff --git a/tooling/client/domain/heapprofiler_client.h b/tooling/client/domain/heapprofiler_client.h index bb4f99f0..b1071756 100644 --- a/tooling/client/domain/heapprofiler_client.h +++ b/tooling/client/domain/heapprofiler_client.h @@ -38,18 +38,18 @@ enum HeapProfilerEvent { }; class HeapProfilerClient final { public: - HeapProfilerClient() = default; + HeapProfilerClient(uint32_t sessionId) : sessionId_(sessionId) {} ~HeapProfilerClient() = default; - bool DispatcherCmd(int id, const std::string &cmd, const std::string &arg, std::string* reqStr); - std::string HeapDumpCommand(int id); - std::string AllocationTrackCommand(int id); - std::string AllocationTrackStopCommand(int id); - std::string Enable(int id); - std::string Disable(int id); - std::string Samping(int id); - std::string SampingStop(int id); - std::string CollectGarbage(int id); + bool DispatcherCmd(const std::string &cmd, const std::string &arg); + int HeapDumpCommand(); + int AllocationTrackCommand(); + int AllocationTrackStopCommand(); + int Enable(); + int Disable(); + int Samping(); + int SampingStop(); + int CollectGarbage(); void RecvReply(std::unique_ptr json); bool WriteHeapProfilerForFile(const std::string &fileName, const std::string &data); @@ -58,6 +58,7 @@ private: std::map idEventMap_; std::string path_; bool isAllocationMsg_ {false}; + uint32_t sessionId_; }; } // OHOS::ArkCompiler::Toolchain #endif \ No newline at end of file diff --git a/tooling/client/domain/profiler_client.cpp b/tooling/client/domain/profiler_client.cpp index f56b7954..9cdf93da 100644 --- a/tooling/client/domain/profiler_client.cpp +++ b/tooling/client/domain/profiler_client.cpp @@ -17,6 +17,7 @@ #include "tooling/base/pt_types.h" #include "common/log_wrapper.h" #include "tooling/client/utils/utils.h" +#include "session/session.h" #include #include @@ -26,30 +27,31 @@ using Result = panda::ecmascript::tooling::Result; using Profile = panda::ecmascript::tooling::Profile; namespace OHOS::ArkCompiler::Toolchain { -ProfilerSingleton ProfilerSingleton::instance_; -bool ProfilerClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr) +bool ProfilerClient::DispatcherCmd(const std::string &cmd) { - std::map> dispatcherTable { - { "cpuprofile", std::bind(&ProfilerClient::CpuprofileCommand, this, id)}, - { "cpuprofile-stop", std::bind(&ProfilerClient::CpuprofileStopCommand, this, id)}, - { "cpuprofile-setSamplingInterval", std::bind(&ProfilerClient::SetSamplingIntervalCommand, this, id)}, - { "cpuprofile-enable", std::bind(&ProfilerClient::CpuprofileEnableCommand, this, id)}, - { "cpuprofile-disable", std::bind(&ProfilerClient::CpuprofileDisableCommand, this, id)}, + std::map> dispatcherTable { + { "cpuprofile", std::bind(&ProfilerClient::CpuprofileCommand, this)}, + { "cpuprofile-stop", std::bind(&ProfilerClient::CpuprofileStopCommand, this)}, + { "cpuprofile-setSamplingInterval", std::bind(&ProfilerClient::SetSamplingIntervalCommand, this)}, + { "cpuprofile-enable", std::bind(&ProfilerClient::CpuprofileEnableCommand, this)}, + { "cpuprofile-disable", std::bind(&ProfilerClient::CpuprofileDisableCommand, this)}, }; auto entry = dispatcherTable.find(cmd); if (entry == dispatcherTable.end()) { - *reqStr = "Unknown commond: " + cmd; - LOGI("DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("Unknown commond: %{public}s", cmd.c_str()); return false; } - *reqStr = entry->second(); + entry->second(); LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); return true; } -std::string ProfilerClient::CpuprofileEnableCommand(int id) +int ProfilerClient::CpuprofileEnableCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, "cpuprofileenable"); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -57,11 +59,19 @@ std::string ProfilerClient::CpuprofileEnableCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Profiler"); + } + return 0; } -std::string ProfilerClient::CpuprofileDisableCommand(int id) +int ProfilerClient::CpuprofileDisableCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, "cpuprofiledisable"); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -69,11 +79,19 @@ std::string ProfilerClient::CpuprofileDisableCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Profiler"); + } + return 0; } -std::string ProfilerClient::CpuprofileCommand(int id) +int ProfilerClient::CpuprofileCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, "cpuprofile"); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -81,11 +99,19 @@ std::string ProfilerClient::CpuprofileCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Profiler"); + } + return 0; } -std::string ProfilerClient::CpuprofileStopCommand(int id) +int ProfilerClient::CpuprofileStopCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, "cpuprofilestop"); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -93,11 +119,19 @@ std::string ProfilerClient::CpuprofileStopCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Profiler"); + } + return 0; } -std::string ProfilerClient::SetSamplingIntervalCommand(int id) +int ProfilerClient::SetSamplingIntervalCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idEventMap_.emplace(id, "setsamplinginterval"); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -106,12 +140,12 @@ std::string ProfilerClient::SetSamplingIntervalCommand(int id) std::unique_ptr params = PtJson::CreateObject(); params->Add("interval", interval_); request->Add("params", params); - return request->Stringify(); -} -ProfilerSingleton& ProfilerSingleton::GetInstance() -{ - return instance_; + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Profiler"); + } + return 0; } void ProfilerClient::RecvProfilerResult(std::unique_ptr json) @@ -149,10 +183,12 @@ void ProfilerClient::RecvProfilerResult(std::unique_ptr json) return; } - ProfilerSingleton& pro = ProfilerSingleton::GetInstance(); - std::string fileName = "CPU-" + std::string(date) + "T" + std::string(time) + ".cpuprofile"; + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + ProfilerSingleton &pro = session->GetProfilerSingleton(); + std::string fileName = "CPU-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" + std::string(time) + + ".cpuprofile"; std::string cpufile = pro.GetAddress() + fileName; - std::cout << "cpuprofile file name is " << cpufile << std::endl; + std::cout << "session " << sessionId_ << " cpuprofile file name is " << cpufile << std::endl; std::cout << ">>> "; fflush(stdout); WriteCpuProfileForFile(cpufile, profile->Stringify()); @@ -171,7 +207,8 @@ bool ProfilerClient::WriteCpuProfileForFile(const std::string &fileName, const s ofs.write(data.c_str(), strSize); ofs.close(); ofs.clear(); - ProfilerSingleton& pro = ProfilerSingleton::GetInstance(); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + ProfilerSingleton &pro = session->GetProfilerSingleton(); pro.SetAddress(""); return true; } diff --git a/tooling/client/domain/profiler_client.h b/tooling/client/domain/profiler_client.h index 7f2ee833..5c1681b7 100644 --- a/tooling/client/domain/profiler_client.h +++ b/tooling/client/domain/profiler_client.h @@ -27,7 +27,7 @@ namespace OHOS::ArkCompiler::Toolchain { using PtJson = panda::ecmascript::tooling::PtJson; class ProfilerSingleton { public: - static ProfilerSingleton& GetInstance(); + ProfilerSingleton() = default; void AddCpuName(const std::string &data) { @@ -55,29 +55,28 @@ public: private: std::vector cpulist_; std::string address_ = ""; - static ProfilerSingleton instance_; - ProfilerSingleton() = default; ProfilerSingleton(const ProfilerSingleton&) = delete; ProfilerSingleton& operator=(const ProfilerSingleton&) = delete; }; class ProfilerClient final { public: - ProfilerClient() = default; + ProfilerClient(uint32_t sessionId) : sessionId_(sessionId) {} ~ProfilerClient() = default; - bool DispatcherCmd(int id, const std::string &cmd, std::string* reqStr); - std::string CpuprofileCommand(int id); - std::string CpuprofileStopCommand(int id); - std::string SetSamplingIntervalCommand(int id); - std::string CpuprofileEnableCommand(int id); - std::string CpuprofileDisableCommand(int id); + bool DispatcherCmd(const std::string &cmd); + int CpuprofileCommand(); + int CpuprofileStopCommand(); + int SetSamplingIntervalCommand(); + int CpuprofileEnableCommand(); + int CpuprofileDisableCommand(); bool WriteCpuProfileForFile(const std::string &fileName, const std::string &data); void RecvProfilerResult(std::unique_ptr json); void SetSamplingInterval(int interval); private: int32_t interval_ = 0; + int32_t sessionId_; std::map idEventMap_ {}; }; } // OHOS::ArkCompiler::Toolchain diff --git a/tooling/client/domain/runtime_client.cpp b/tooling/client/domain/runtime_client.cpp index 3731c4dd..23bea9e7 100644 --- a/tooling/client/domain/runtime_client.cpp +++ b/tooling/client/domain/runtime_client.cpp @@ -18,34 +18,37 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/variable_manager.h" #include "tooling/base/pt_json.h" +#include "session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { -bool RuntimeClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr) +bool RuntimeClient::DispatcherCmd(const std::string &cmd) { - std::map> dispatcherTable { - { "heapusage", std::bind(&RuntimeClient::HeapusageCommand, this, id)}, - { "runtime-enable", std::bind(&RuntimeClient::RuntimeEnableCommand, this, id)}, - { "runtime-disable", std::bind(&RuntimeClient::RuntimeDisableCommand, this, id)}, - { "print", std::bind(&RuntimeClient::GetPropertiesCommand, this, id)}, - { "print2", std::bind(&RuntimeClient::GetPropertiesCommand2, this, id)}, - { "run", std::bind(&RuntimeClient::RunIfWaitingForDebuggerCommand, this, id)}, + std::map> dispatcherTable { + { "heapusage", std::bind(&RuntimeClient::HeapusageCommand, this)}, + { "runtime-enable", std::bind(&RuntimeClient::RuntimeEnableCommand, this)}, + { "runtime-disable", std::bind(&RuntimeClient::RuntimeDisableCommand, this)}, + { "print", std::bind(&RuntimeClient::GetPropertiesCommand, this)}, + { "print2", std::bind(&RuntimeClient::GetPropertiesCommand2, this)}, + { "run", std::bind(&RuntimeClient::RunIfWaitingForDebuggerCommand, this)}, }; auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end()) { - *reqStr = entry->second(); + entry->second(); LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); return true; } else { - *reqStr = "Unknown commond: " + cmd; - LOGI("RuntimeClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("Unknown commond: %{public}s", cmd.c_str()); return false; } } -std::string RuntimeClient::HeapusageCommand(int id) +int RuntimeClient::HeapusageCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idMethodMap_[id] = std::make_tuple("getHeapUsage", ""); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -53,11 +56,19 @@ std::string RuntimeClient::HeapusageCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Runtime"); + } + return 0; } -std::string RuntimeClient::RuntimeEnableCommand(int id) +int RuntimeClient::RuntimeEnableCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idMethodMap_[id] = std::make_tuple("enable", ""); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -65,11 +76,19 @@ std::string RuntimeClient::RuntimeEnableCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Runtime"); + } + return 0; } -std::string RuntimeClient::RuntimeDisableCommand(int id) +int RuntimeClient::RuntimeDisableCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idMethodMap_[id] = std::make_tuple("disable", ""); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -77,11 +96,19 @@ std::string RuntimeClient::RuntimeDisableCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Runtime"); + } + return 0; } -std::string RuntimeClient::RunIfWaitingForDebuggerCommand(int id) +int RuntimeClient::RunIfWaitingForDebuggerCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idMethodMap_[id] = std::make_tuple("runIfWaitingForDebugger", ""); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -89,11 +116,19 @@ std::string RuntimeClient::RunIfWaitingForDebuggerCommand(int id) std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Runtime"); + } + return 0; } -std::string RuntimeClient::GetPropertiesCommand(int id) +int RuntimeClient::GetPropertiesCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idMethodMap_[id] = std::make_tuple("getProperties", objectId_); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -105,11 +140,19 @@ std::string RuntimeClient::GetPropertiesCommand(int id) params->Add("objectId", objectId_.c_str()); params->Add("ownProperties", true); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Runtime"); + } + return 0; } -std::string RuntimeClient::GetPropertiesCommand2(int id) +int RuntimeClient::GetPropertiesCommand2() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + idMethodMap_[id] = std::make_tuple("getProperties", objectId_); std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); @@ -121,7 +164,12 @@ std::string RuntimeClient::GetPropertiesCommand2(int id) params->Add("objectId", "0"); params->Add("ownProperties", false); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Runtime"); + } + return 0; } void RuntimeClient::RecvReply(std::unique_ptr json) @@ -198,8 +246,9 @@ void RuntimeClient::HandleGetProperties(std::unique_ptr json, const int return; } - StackManager &stackManager = StackManager::GetInstance(); - VariableManager &variableManager = VariableManager::GetInstance(); + Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + StackManager &stackManager = session->GetStackManager(); + VariableManager &variableManager = session->GetVariableManager(); std::map> treeInfo = stackManager.GetScopeChainInfo(); if (isInitializeTree_) { variableManager.ClearVariableInfo(); @@ -242,7 +291,8 @@ void RuntimeClient::HandleHeapUsage(std::unique_ptr json) return; } - VariableManager &variableManager = VariableManager::GetInstance(); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + VariableManager &variableManager = session->GetVariableManager(); std::unique_ptr heapUsageReturns = GetHeapUsageReturns::Create(*result); variableManager.SetHeapUsageInfo(std::move(heapUsageReturns)); variableManager.ShowHeapUsageInfo(); diff --git a/tooling/client/domain/runtime_client.h b/tooling/client/domain/runtime_client.h index 3d428c19..12e12705 100644 --- a/tooling/client/domain/runtime_client.h +++ b/tooling/client/domain/runtime_client.h @@ -26,16 +26,16 @@ using Result = panda::ecmascript::tooling::Result; namespace OHOS::ArkCompiler::Toolchain { class RuntimeClient final { public: - RuntimeClient() = default; + RuntimeClient(int32_t sessionId) : sessionId_(sessionId) {} ~RuntimeClient() = default; - bool DispatcherCmd(int id, const std::string &cmd, std::string *reqStr); - std::string HeapusageCommand(int id); - std::string RuntimeEnableCommand(int id); - std::string RuntimeDisableCommand(int id); - std::string RunIfWaitingForDebuggerCommand(int id); - std::string GetPropertiesCommand(int id); - std::string GetPropertiesCommand2(int id); + bool DispatcherCmd(const std::string &cmd); + int HeapusageCommand(); + int RuntimeEnableCommand(); + int RuntimeDisableCommand(); + int RunIfWaitingForDebuggerCommand(); + int GetPropertiesCommand(); + int GetPropertiesCommand2(); std::string GetMethodById(const int &id); std::string GetRequestObjectIdById(const int &id); void RecvReply(std::unique_ptr json); @@ -61,6 +61,7 @@ private: std::map> idMethodMap_ {}; std::string objectId_ {"0"}; bool isInitializeTree_ {true}; + int32_t sessionId_; }; } // OHOS::ArkCompiler::Toolchain #endif \ No newline at end of file diff --git a/tooling/client/domain/test_client.cpp b/tooling/client/domain/test_client.cpp index 66355941..d6c831cf 100644 --- a/tooling/client/domain/test_client.cpp +++ b/tooling/client/domain/test_client.cpp @@ -21,44 +21,59 @@ using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { -bool TestClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr) +bool TestClient::DispatcherCmd(const std::string &cmd) { - std::map> dispatcherTable { - { "success", std::bind(&TestClient::SuccessCommand, this, id)}, - { "fail", std::bind(&TestClient::FailCommand, this, id)}, + std::map> dispatcherTable { + { "success", std::bind(&TestClient::SuccessCommand, this)}, + { "fail", std::bind(&TestClient::FailCommand, this)}, }; auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end()) { - *reqStr = entry->second(); + entry->second(); LOGI("TestClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); return true; } else { - *reqStr = "Unknown commond: " + cmd; - LOGI("TestClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("Unknown commond: %{public}s", cmd.c_str()); return false; } } -std::string TestClient::SuccessCommand(int id) +int TestClient::SuccessCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Test.success"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Test"); + } + return 0; } -std::string TestClient::FailCommand(int id) +int TestClient::FailCommand() { + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + std::unique_ptr request = PtJson::CreateObject(); request->Add("id", id); request->Add("method", "Test.fail"); std::unique_ptr params = PtJson::CreateObject(); request->Add("params", params); - return request->Stringify(); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Test"); + } + return 0; } } // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/manager/breakpoint_manager.cpp b/tooling/client/manager/breakpoint_manager.cpp index 83b94a55..5878635c 100644 --- a/tooling/client/manager/breakpoint_manager.cpp +++ b/tooling/client/manager/breakpoint_manager.cpp @@ -17,16 +17,11 @@ #include "common/log_wrapper.h" #include "tooling/client/utils/utils.h" +#include "session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; using Result = panda::ecmascript::tooling::Result; namespace OHOS::ArkCompiler::Toolchain { -BreakPointManager BreakPointManager::instance_; -BreakPointManager& BreakPointManager::GetInstance() -{ - return instance_; -} - void BreakPointManager::Createbreaklocation(const std::unique_ptr json) { if (json == nullptr) { diff --git a/tooling/client/manager/breakpoint_manager.h b/tooling/client/manager/breakpoint_manager.h index 115702b3..76958898 100644 --- a/tooling/client/manager/breakpoint_manager.h +++ b/tooling/client/manager/breakpoint_manager.h @@ -36,7 +36,7 @@ struct Breaklocation { }; class BreakPointManager { public: - static BreakPointManager& GetInstance(); + BreakPointManager(int32_t sessionId) : sessionId_(sessionId) {} void Createbreaklocation(const std::unique_ptr json); void Show(); @@ -44,9 +44,8 @@ public: std::vector Getbreaklist() const; private: - static BreakPointManager instance_; + [[maybe_unused]] int32_t sessionId_; std::vector breaklist_ {}; - BreakPointManager() = default; BreakPointManager(const BreakPointManager&) = delete; BreakPointManager& operator=(const BreakPointManager&) = delete; }; diff --git a/tooling/client/manager/domain_manager.cpp b/tooling/client/manager/domain_manager.cpp index 75a35546..f4f0cdfe 100644 --- a/tooling/client/manager/domain_manager.cpp +++ b/tooling/client/manager/domain_manager.cpp @@ -18,10 +18,17 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/breakpoint_manager.h" #include "tooling/base/pt_json.h" +#include "session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; using Result = panda::ecmascript::tooling::Result; namespace OHOS::ArkCompiler::Toolchain { +DomainManager::DomainManager(uint32_t sessionId) + : sessionId_(sessionId), heapProfilerClient_(sessionId), profilerClient_(sessionId), + debuggerClient_(sessionId), runtimeClient_(sessionId) +{ +} + void DomainManager::DispatcherReply(char* msg) { std::string decMessage = std::string(msg); diff --git a/tooling/client/manager/domain_manager.h b/tooling/client/manager/domain_manager.h index 0c6dc586..3d3aaafb 100644 --- a/tooling/client/manager/domain_manager.h +++ b/tooling/client/manager/domain_manager.h @@ -27,7 +27,7 @@ namespace OHOS::ArkCompiler::Toolchain { class DomainManager { public: - DomainManager() = default; + explicit DomainManager(uint32_t sessionId); ~DomainManager() = default; void DispatcherReply(char* msg); @@ -80,6 +80,7 @@ public: } private: + [[maybe_unused]] uint32_t sessionId_; HeapProfilerClient heapProfilerClient_ {}; ProfilerClient profilerClient_ {}; DebuggerClient debuggerClient_ {}; diff --git a/tooling/client/manager/message_manager.h b/tooling/client/manager/message_manager.h new file mode 100755 index 00000000..1be9914a --- /dev/null +++ b/tooling/client/manager/message_manager.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_TOOLING_CLIENT_MANAGER_MESSAGE_MANAGER_H +#define ECMASCRIPT_TOOLING_CLIENT_MANAGER_MESSAGE_MANAGER_H + +#include + +namespace OHOS::ArkCompiler::Toolchain { +class MessageManager final { +public: + ~MessageManager() + { + uv_mutex_destroy(&messageMutex_); + } + + static MessageManager& getInstance() + { + static MessageManager instance; + return instance; + } + + void MessagePush(uint32_t sessionId, std::string& message) + { + uv_mutex_lock(&messageMutex_); + messageQue_.push(std::make_pair(sessionId, std::move(message))); + uv_mutex_unlock(&messageMutex_); + } + + bool MessagePop(uint32_t& sessionId, std::string& message) + { + uv_mutex_lock(&messageMutex_); + if (messageQue_.empty()) { + uv_mutex_unlock(&messageMutex_); + return false; + } + + sessionId = messageQue_.front().first; + message = messageQue_.front().second; + messageQue_.pop(); + + uv_mutex_unlock(&messageMutex_); + return true; + } + +private: + MessageManager() + { + uv_mutex_init(&messageMutex_); + } + MessageManager(const MessageManager&) = delete; + MessageManager& operator=(const MessageManager&) = delete; + + uv_mutex_t messageMutex_; + std::queue> messageQue_; +}; +} // OHOS::ArkCompiler::Toolchain +#endif \ No newline at end of file diff --git a/tooling/client/manager/stack_manager.cpp b/tooling/client/manager/stack_manager.cpp index 0dd28a25..3468da22 100644 --- a/tooling/client/manager/stack_manager.cpp +++ b/tooling/client/manager/stack_manager.cpp @@ -15,14 +15,9 @@ #include "tooling/client/manager/stack_manager.h" #include "common/log_wrapper.h" +#include "session/session.h" namespace OHOS::ArkCompiler::Toolchain { -StackManager StackManager::instance_; -StackManager& StackManager::GetInstance() -{ - return instance_; -} - void StackManager::SetCallFrames(std::map> callFrames) { for (auto &callFrame : callFrames) { diff --git a/tooling/client/manager/stack_manager.h b/tooling/client/manager/stack_manager.h index bca47157..99c65e32 100644 --- a/tooling/client/manager/stack_manager.h +++ b/tooling/client/manager/stack_manager.h @@ -30,7 +30,7 @@ using Scope = panda::ecmascript::tooling::Scope; namespace OHOS::ArkCompiler::Toolchain { class StackManager final { public: - static StackManager& GetInstance(); + StackManager(int32_t sessionId) : sessionId_(sessionId) {} std::map> GetScopeChainInfo(); void SetCallFrames(std::map> callFrames); @@ -39,9 +39,8 @@ public: void PrintScopeChainInfo(const std::map>& scopeInfos); private: - static StackManager instance_; + [[maybe_unused]] int32_t sessionId_; std::map> callFrames_ {}; - StackManager() = default; StackManager(const StackManager&) = delete; StackManager& operator=(const StackManager&) = delete; }; diff --git a/tooling/client/manager/variable_manager.cpp b/tooling/client/manager/variable_manager.cpp index 08b2cf3b..38e3b259 100644 --- a/tooling/client/manager/variable_manager.cpp +++ b/tooling/client/manager/variable_manager.cpp @@ -21,7 +21,6 @@ using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { -VariableManager VariableManager::instance_; void TreeNode::AddChild(std::unique_ptr descriptor) { children.push_back(std::make_unique(std::move(descriptor))); @@ -253,11 +252,6 @@ int32_t Tree::FindObjectByIndexRecursive(const TreeNode* node, int32_t index) co return 0; } -VariableManager& VariableManager::GetInstance() -{ - return instance_; -} - void VariableManager::SetHeapUsageInfo(std::unique_ptr heapUsageReturns) { heapUsageInfo_.SetUsedSize(heapUsageReturns->GetUsedSize()); diff --git a/tooling/client/manager/variable_manager.h b/tooling/client/manager/variable_manager.h index 0b4eaacc..7bd72b7e 100644 --- a/tooling/client/manager/variable_manager.h +++ b/tooling/client/manager/variable_manager.h @@ -74,7 +74,7 @@ private: class VariableManager final { public: - static VariableManager& GetInstance(); + VariableManager(int32_t sessionId) : sessionId_(sessionId) {} void SetHeapUsageInfo(std::unique_ptr heapUsageReturns); void ShowHeapUsageInfo() const; void ShowVariableInfos() const; @@ -88,8 +88,7 @@ public: void Printinfo() const; private: - VariableManager() = default; - static VariableManager instance_; + [[maybe_unused]] int32_t sessionId_; GetHeapUsageReturns heapUsageInfo_ {}; Tree variableInfo_ {0}; VariableManager(const VariableManager&) = delete; diff --git a/tooling/client/session/session.cpp b/tooling/client/session/session.cpp new file mode 100755 index 00000000..48b350aa --- /dev/null +++ b/tooling/client/session/session.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "session/session.h" + +#include "common/log_wrapper.h" +#include "manager/breakpoint_manager.h" +#include "manager/message_manager.h" +#include "pt_json.h" +#include "utils/utils.h" + +#include + +using PtJson = panda::ecmascript::tooling::PtJson; +using Result = panda::ecmascript::tooling::Result; +namespace OHOS::ArkCompiler::Toolchain { +uv_async_t* g_socketSignal; +void SocketMessageThread(void *arg) +{ + int sessionId = *(uint32_t *)arg; + Session *session = SessionManager::getInstance().GetSessionById(sessionId); + + session->SocketMessageLoop(); +} + +Session::Session(uint32_t sessionId, std::string& sockInfo) + : sessionId_(sessionId), sockInfo_(sockInfo), domainManager_(sessionId), breakpoint_(sessionId), + stackManager_(sessionId), variableManager_(sessionId) +{ +} + +void Session::SocketMessageLoop() +{ + while (cliSocket_.IsConnected()) { + std::string decMessage = cliSocket_.Decode(); + uint32_t len = decMessage.length(); + if (len == 0) { + continue; + } + LOGE("arkdb [%{public}u] message = %{public}s", sessionId_, decMessage.c_str()); + + MessageManager::getInstance().MessagePush(sessionId_, decMessage); + + if (uv_is_active(reinterpret_cast(g_socketSignal))) { + uv_async_send(g_socketSignal); + } + } +} + +int Session::Start() +{ + uint32_t port = 0; + if (Utils::StrToUInt(sockInfo_.c_str(), &port)) { + if ((port <= 0) || (port >= 65535)) { // 65535: max port + LOGE("arkdb:InitToolchainWebSocketForPort the port = %{public}d is wrong.", port); + return -1; + } + if (!cliSocket_.InitToolchainWebSocketForPort(port, 5)) { // 5: five times + LOGE("arkdb:InitToolchainWebSocketForPort failed"); + return -1; + } + } else { + if (!cliSocket_.InitToolchainWebSocketForSockName(sockInfo_)) { + LOGE("arkdb:InitToolchainWebSocketForSockName failed"); + return -1; + } + } + + if (!cliSocket_.ClientSendWSUpgradeReq()) { + LOGE("arkdb:ClientSendWSUpgradeReq failed"); + return -1; + } + if (!cliSocket_.ClientRecvWSUpgradeRsp()) { + LOGE("arkdb:ClientRecvWSUpgradeRsp failed"); + return -1; + } + + uv_thread_create(&socketTid_, SocketMessageThread, &sessionId_); + + return 0; +} + +int Session::Stop() +{ + LOGE("arkdb session [%{public}u] Stop", sessionId_); + cliSocket_.Close(); + return 0; +} + +int SessionManager::CreateSessionById(uint32_t sessionId, std::string& sockInfo) +{ + sessions_[sessionId] = std::make_unique(sessionId, sockInfo); + if (sessions_[sessionId]->Start()) { + sessions_[sessionId] = nullptr; + return -1; + } + + return 0; +} + +int SessionManager::CreateNewSession(std::string sockInfo) +{ + uint32_t sessionId = MAX_SESSION_NUM; + for (uint32_t i = 0; i < MAX_SESSION_NUM; ++i) { + if (sessions_[i] == nullptr) { + if (sessionId == MAX_SESSION_NUM) { + sessionId = i; + } + continue; + } + if (sessions_[i]->GetSockInfo() == sockInfo) { + return -1; + } + } + + if (sessionId < MAX_SESSION_NUM) { + return CreateSessionById(sessionId, sockInfo); + } + + return -1; +} + +int SessionManager::CreateDefaultSession(std::string sockInfo) +{ + return CreateSessionById(0, sockInfo); +} + +int SessionManager::DelSessionById(uint32_t sessionId) +{ + Session* session = GetSessionById(sessionId); + if (session == nullptr) { + return -1; + } + session->Stop(); + sessions_[sessionId] = nullptr; + + if (sessionId == currentSessionId_) { + currentSessionId_ = 0; + std::cout << "session switch to 0" << std::endl; + } + + return 0; +} + +int SessionManager::SessionList() +{ + for (uint32_t i = 0; i < MAX_SESSION_NUM; ++i) { + if (sessions_[i] != nullptr) { + std::string flag = (i == currentSessionId_) ? "* " : " "; + std::string sockState = sessions_[i]->GetSocketStateString(); + std::cout << flag << i << ": "; + std::cout << std::setw(32) << std::left << sessions_[i]->GetSockInfo(); // 32: max length of socket info + std::cout << sockState << std::endl; + } + } + return 0; +} + +int SessionManager::SessionSwitch(uint32_t sessionId) +{ + Session* session = GetSessionById(sessionId); + if (session == nullptr) { + return -1; + } + currentSessionId_ = sessionId; + return 0; +} + +void SessionManager::CmdForAllSessions(CmdForAllCB callback) +{ + for (uint32_t sessionId = 0; sessionId < MAX_SESSION_NUM; ++sessionId) { + if (sessions_[sessionId] != nullptr) { + std::cout << "Executing command in session " << sessionId << ":" << std::endl; + callback(sessionId); + } + } +} +} \ No newline at end of file diff --git a/tooling/client/session/session.h b/tooling/client/session/session.h new file mode 100755 index 00000000..0c889fe4 --- /dev/null +++ b/tooling/client/session/session.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_TOOLING_CLIENT_SESSION_H +#define ECMASCRIPT_TOOLING_CLIENT_SESSION_H + +#include +#include +#include +#include +#include +#include +#include + +#include "manager/domain_manager.h" +#include "manager/breakpoint_manager.h" +#include "manager/stack_manager.h" +#include "manager/variable_manager.h" +#include "websocket/websocket_client.h" + +namespace OHOS::ArkCompiler::Toolchain { +using CmdForAllCB = std::function; +extern uv_async_t* g_socketSignal; +class Session { +public: + explicit Session(uint32_t sessionId, std::string& sockInfo); + ~Session() + { + Stop(); + } + + void SocketMessageLoop(); + int Start(); + int Stop(); + void CmdForAllSession(CmdForAllCB callback); + + uint32_t GetMessageId() + { + return messageId_.fetch_add(1); + } + + std::string& GetSockInfo() + { + return sockInfo_; + } + + bool ClientSendReq(const std::string &message) + { + return cliSocket_.ClientSendReq(message); + } + + DomainManager& GetDomainManager() + { + return domainManager_; + } + + BreakPointManager& GetBreakPointManager() + { + return breakpoint_; + } + + StackManager& GetStackManager() + { + return stackManager_; + } + + VariableManager& GetVariableManager() + { + return variableManager_; + } + + ProfilerSingleton& GetProfilerSingleton() + { + return profiler_; + } + + std::string GetSocketStateString() + { + return cliSocket_.GetSocketStateString(); + } + + void ProcSocketMsg(char* msg) + { + domainManager_.DispatcherReply(msg); + } + +private: + uint32_t sessionId_; + std::string sockInfo_; + DomainManager domainManager_; + WebsocketClient cliSocket_; + uv_thread_t socketTid_; + std::atomic messageId_ {1}; + BreakPointManager breakpoint_; + StackManager stackManager_; + VariableManager variableManager_; + ProfilerSingleton profiler_; +}; + +constexpr uint32_t MAX_SESSION_NUM = 8; +class SessionManager { +public: + static SessionManager& getInstance() + { + static SessionManager instance; + return instance; + } + + uint32_t GetCurrentSessionId() + { + return currentSessionId_; + } + + Session *GetCurrentSession() + { + if (currentSessionId_ >= MAX_SESSION_NUM || sessions_[currentSessionId_] == nullptr) { + return nullptr; + } + return sessions_[currentSessionId_].get(); + } + + Session *GetSessionById(uint32_t sessionId) + { + if (sessionId >= MAX_SESSION_NUM || sessions_[sessionId] == nullptr) { + return nullptr; + } + return sessions_[sessionId].get(); + } + + int CreateSessionById(uint32_t sessionId, std::string& sockInfo); + int CreateNewSession(std::string sockInfo); + int CreateDefaultSession(std::string sockInfo); + int DelSessionById(uint32_t sessionId); + int SessionList(); + int SessionSwitch(uint32_t sessionId); + void CmdForAllSessions(CmdForAllCB callback); + +private: + SessionManager() = default; + SessionManager(const SessionManager&) = delete; + SessionManager& operator=(const SessionManager&) = delete; + + std::unique_ptr sessions_[MAX_SESSION_NUM]; + uint32_t currentSessionId_ = 0; +}; +} // namespace OHOS::ArkCompiler::Toolchain +#endif \ No newline at end of file diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 686ef585..3ce9c2a3 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -25,6 +25,7 @@ #include "tooling/client/manager/domain_manager.h" #include "tooling/client/manager/stack_manager.h" #include "tooling/client/manager/variable_manager.h" +#include "session/session.h" namespace OHOS::ArkCompiler::Toolchain { const std::string HELP_MSG = "usage: \n" @@ -75,6 +76,11 @@ const std::string HELP_MSG = "usage: \n" " step-out(so) step-out\n" " step-over(sov) step-over\n" " runtime-disable rt-disable\n" + " session-new add new session\n" + " session-remove del a session\n" + " session-list list all sessions\n" + " session switch session\n" + " forall command for all sessions\n" " success test success\n" " fail test fail\n"; @@ -123,6 +129,10 @@ const std::vector cmdList = { "step-out", "step-over", "runtime-disable", + "session-new", + "session-remove", + "session-list", + "session", "success", "fail" }; @@ -194,6 +204,14 @@ void CliCommand::CreateCommandMap() {std::make_pair("step-over", "sov"), std::bind(&CliCommand::DebuggerCommand, this, "step-over")}, {std::make_pair("runtime-disable", "rt-disable"), std::bind(&CliCommand::RuntimeCommand, this, "runtime-disable")}, + {std::make_pair("session-new", "session-new"), + std::bind(&CliCommand::SessionAddCommand, this, "session-new")}, + {std::make_pair("session-remove", "session-remove"), + std::bind(&CliCommand::SessionDelCommand, this, "session-remove")}, + {std::make_pair("session-list", "session-list"), + std::bind(&CliCommand::SessionListCommand, this, "session-list")}, + {std::make_pair("session", "session"), + std::bind(&CliCommand::SessionSwitchCommand, this, "session")}, {std::make_pair("success", "success"), std::bind(&CliCommand::TestCommand, this, "success")}, {std::make_pair("fail", "fail"), @@ -204,32 +222,25 @@ void CliCommand::CreateCommandMap() ErrCode CliCommand::HeapProfilerCommand(const std::string &cmd) { std::cout << "exe success, cmd is " << cmd << std::endl; - std::string request; - bool result = false; - HeapProfilerClient &heapProfilerClient = domainManager_.GetHeapProfilerClient(); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + DomainManager &domainManager = session->GetDomainManager(); + HeapProfilerClient &heapProfilerClient = domainManager.GetHeapProfilerClient(); VecStr argList = GetArgList(); if (argList.empty()) { argList.push_back("/data/"); } - result = heapProfilerClient.DispatcherCmd(id_, cmd, argList[0], &request); - if (result) { - cliSocket_.ClientSendReq(request); - if (domainManager_.GetDomainById(id_).empty()) { - domainManager_.SetDomainById(id_, "HeapProfiler"); - } - } else { - return ErrCode::ERR_FAIL; - } - return ErrCode::ERR_OK; + + bool result = heapProfilerClient.DispatcherCmd(cmd, argList[0]); + return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL; } ErrCode CliCommand::CpuProfileCommand(const std::string &cmd) { std::cout << "exe success, cmd is " << cmd << std::endl; - std::string request; - bool result = false; - ProfilerClient &profilerClient = domainManager_.GetProfilerClient(); - ProfilerSingleton& pro = ProfilerSingleton::GetInstance(); + Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + DomainManager &domainManager = session->GetDomainManager(); + ProfilerClient &profilerClient = domainManager.GetProfilerClient(); + ProfilerSingleton &pro = session->GetProfilerSingleton(); if (cmd == "cpuprofile-show") { pro.ShowCpuFile(); return ErrCode::ERR_OK; @@ -240,25 +251,17 @@ ErrCode CliCommand::CpuProfileCommand(const std::string &cmd) if (cmd == "cpuprofile-stop" && GetArgList().size() == 1) { pro.SetAddress(GetArgList()[0]); } - result = profilerClient.DispatcherCmd(id_, cmd, &request); - if (result) { - cliSocket_.ClientSendReq(request); - if (domainManager_.GetDomainById(id_).empty()) { - domainManager_.SetDomainById(id_, "Profiler"); - } - } else { - return ErrCode::ERR_FAIL; - } - return ErrCode::ERR_OK; + bool result = profilerClient->DispatcherCmd(cmd); + return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL; } ErrCode CliCommand::DebuggerCommand(const std::string &cmd) { std::cout << "exe success, cmd is " << cmd << std::endl; - std::string request; bool result = false; - DebuggerClient &debuggerCli = domainManager_.GetDebuggerClient(); - BreakPointManager &breakpoint = BreakPointManager::GetInstance(); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + DebuggerClient &debuggerCli = session->GetDomainManager().GetDebuggerClient(); + BreakPointManager &breakpoint = session->GetBreakPointManager(); if (cmd == "display") { breakpoint.Show(); return ErrCode::ERR_OK; @@ -276,12 +279,12 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd) } if (cmd == "step-into" || cmd == "step-out" || cmd == "step-over") { - RuntimeClient &runtimeClient = domainManager_.GetRuntimeClient(); + RuntimeClient &runtimeClient = session->GetDomainManager.GetRuntimeClient(); runtimeClient.SetIsInitializeTree(true); } if (cmd == "showstack") { - StackManager &stackManager = StackManager::GetInstance(); + StackManager &stackManager = session->GetStackManager(); stackManager.ShowCallFrames(); } @@ -289,58 +292,93 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd) debuggerCli.AddBreakPointInfo(GetArgList()[0], std::stoi(GetArgList()[1])); } - result = debuggerCli.DispatcherCmd(id_, cmd, &request); - if (result) { - cliSocket_.ClientSendReq(request); - if (domainManager_.GetDomainById(id_).empty()) { - domainManager_.SetDomainById(id_, "Debugger"); - } - } else { - return ErrCode::ERR_FAIL; - } - return ErrCode::ERR_OK; + result = debuggerCli.DispatcherCmd(cmd); + return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL; } ErrCode CliCommand::RuntimeCommand(const std::string &cmd) { std::cout << "exe success, cmd is " << cmd << std::endl; - std::string request; bool result = false; - RuntimeClient &runtimeClient = domainManager_.GetRuntimeClient(); + Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + RuntimeClient &runtimeClient = session->GetDomainManager.GetRuntimeClient(); if (cmd == "print" && GetArgList().size() == 1) { runtimeClient.SetIsInitializeTree(false); - VariableManager &variableManager = VariableManager::GetInstance(); + VariableManager &variableManager = session->GetVariableManager(); int32_t objectId = variableManager.FindObjectIdWithIndex(std::stoi(GetArgList()[0])); runtimeClient.SetObjectId(std::to_string(objectId)); } - result = runtimeClient.DispatcherCmd(id_, cmd, &request); + result = runtimeClient->DispatcherCmd(cmd); if (result) { - cliSocket_.ClientSendReq(request); runtimeClient.SetObjectId("0"); - if (domainManager_.GetDomainById(id_).empty()) { - domainManager_.SetDomainById(id_, "Runtime"); - } } else { return ErrCode::ERR_FAIL; } return ErrCode::ERR_OK; } +ErrCode CliCommand::SessionAddCommand([[maybe_unused]] const std::string &cmd) +{ + VecStr argList = GetArgList(); + if (argList.size() >= 1) { + if (!SessionManager::getInstance().CreateNewSession(argList[0].c_str())) { + std::cout << "session create success" << std::endl; + return ErrCode::ERR_OK; + } + } + + std::cout << "session add failed" << std::endl; + return ErrCode::ERR_FAIL; +} + +ErrCode CliCommand::SessionDelCommand([[maybe_unused]] const std::string &cmd) +{ + VecStr argList = GetArgList(); + if (argList.size() >= 1) { + uint32_t sessionId = 0; + if (Utils::StrToUInt(argList[0].c_str(), &sessionId)) { + if (sessionId == 0) { + std::cout << "cannot remove default session 0" << std::endl; + return ErrCode::ERR_OK; + } + if (SessionManager::getInstance().DelSessionById(sessionId) == 0) { + std::cout << "session remove success" << std::endl; + return ErrCode::ERR_OK; + } + } + } + + return ErrCode::ERR_FAIL; +} + +ErrCode CliCommand::SessionListCommand([[maybe_unused]] const std::string &cmd) +{ + SessionManager::getInstance().SessionList(); + return ErrCode::ERR_OK; +} + +ErrCode CliCommand::SessionSwitchCommand([[maybe_unused]] const std::string &cmd) +{ + VecStr argList = GetArgList(); + if (argList.size() >= 1) { + uint32_t sessionId = 0; + if (Utils::StrToUInt(argList[0].c_str(), &sessionId)) { + if (SessionManager::getInstance().SessionSwitch(sessionId) == 0) { + std::cout << "session switch success" << std::endl; + return ErrCode::ERR_OK; + } + } + } + return ErrCode::ERR_OK; +} + ErrCode CliCommand::TestCommand(const std::string &cmd) { - std::string request; - bool result = false; if (cmd == "success" || cmd == "fail") { TestClient &testClient = domainManager_.GetTestClient(); - result = testClient.DispatcherCmd(id_, cmd, &request); - if (result) { - cliSocket_.ClientSendReq(request); - if (domainManager_.GetDomainById(id_).empty()) { - domainManager_.SetDomainById(id_, "Test"); - } - } + testClient.DispatcherCmd(cmd); } else { return ErrCode::ERR_FAIL; } diff --git a/tooling/client/utils/cli_command.h b/tooling/client/utils/cli_command.h index 4b6b7f34..a06e7a21 100644 --- a/tooling/client/utils/cli_command.h +++ b/tooling/client/utils/cli_command.h @@ -27,6 +27,7 @@ #include "tooling/client/manager/domain_manager.h" #include "tooling/client/utils/utils.h" #include "tooling/client/websocket/websocket_client.h" +#include "session/session.h" namespace OHOS::ArkCompiler::Toolchain { using StrPair = std::pair; @@ -39,8 +40,8 @@ enum class ErrCode : uint8_t { class CliCommand { public: - CliCommand(std::vector cliCmdStr, int cmdId, DomainManager &domainManager, WebsocketClient &cliSocket) - : cmd_(cliCmdStr[0]), id_(cmdId), domainManager_(domainManager), cliSocket_(cliSocket) + CliCommand(std::vector cliCmdStr, uint32_t sessionId) + : cmd_(cliCmdStr[0]), sessionId_(sessionId) { for (size_t i = 1; i < cliCmdStr.size(); i++) { argList_.push_back(cliCmdStr[i]); @@ -56,14 +57,13 @@ public: ErrCode DebuggerCommand(const std::string &cmd); ErrCode CpuProfileCommand(const std::string &cmd); ErrCode RuntimeCommand(const std::string &cmd); + ErrCode SessionAddCommand(const std::string &cmd); + ErrCode SessionDelCommand(const std::string &cmd); + ErrCode SessionListCommand(const std::string &cmd); + ErrCode SessionSwitchCommand(const std::string &cmd); ErrCode TestCommand(const std::string &cmd); ErrCode ExecHelpCommand(); - uint32_t GetId() const - { - return id_; - } - VecStr GetArgList() { return argList_; @@ -74,9 +74,7 @@ private: VecStr argList_ {}; std::map> commandMap_; std::string resultReceiver_ = ""; - uint32_t id_ = 0; - DomainManager &domainManager_; - WebsocketClient &cliSocket_; + uint32_t sessionId_; }; } // namespace OHOS::ArkCompiler::Toolchain diff --git a/tooling/client/utils/utils.cpp b/tooling/client/utils/utils.cpp index d35ddc72..dd9c33c2 100644 --- a/tooling/client/utils/utils.cpp +++ b/tooling/client/utils/utils.cpp @@ -53,6 +53,17 @@ bool Utils::GetCurrentTime(char *date, char *tim, size_t size) return true; } +bool Utils::StrToUInt(const char *content, uint32_t *result) +{ + const int dec = 10; + char *endPtr = nullptr; + *result = std::strtoul(content, &endPtr, dec); + if (endPtr == content || *endPtr != '\0') { + return false; + } + return true; +} + std::vector Utils::SplitString(const std::string &str, const std::string &delimiter) { std::size_t strIndex = 0; diff --git a/tooling/client/utils/utils.h b/tooling/client/utils/utils.h index 606df61c..90c61c98 100644 --- a/tooling/client/utils/utils.h +++ b/tooling/client/utils/utils.h @@ -23,6 +23,7 @@ namespace OHOS::ArkCompiler::Toolchain { class Utils { public: static bool GetCurrentTime(char *date, char *tim, size_t size); + static bool StrToUInt(const char *content, uint32_t *result); static std::vector SplitString(const std::string &str, const std::string &delimiter); }; } // OHOS::ArkCompiler::Toolchain diff --git a/tooling/client/websocket/websocket_client.cpp b/tooling/client/websocket/websocket_client.cpp index 15af1887..9cc9f21d 100644 --- a/tooling/client/websocket/websocket_client.cpp +++ b/tooling/client/websocket/websocket_client.cpp @@ -254,11 +254,14 @@ std::string WebsocketClient::Decode() return ""; } char recvbuf[SOCKET_HEADER_LEN + 1]; + errno = 0; if (!Recv(client_, recvbuf, SOCKET_HEADER_LEN, 0)) { - LOGE("WebsocketClient:Decode failed, client websocket disconnect"); - socketState_ = ToolchainSocketState::INITED; - close(client_); - client_ = -1; + if (errno != EAGAIN) { + LOGE("WebsocketClient:Decode failed, client websocket disconnect"); + socketState_ = ToolchainSocketState::INITED; + close(client_); + client_ = -1; + } return ""; } ToolchainWebSocketFrame wsFrame; @@ -425,4 +428,15 @@ bool WebsocketClient::IsConnected() { return socketState_ == ToolchainSocketState::CONNECTED; } + +std::string WebsocketClient::GetSocketStateString() +{ + std::vector stateStr = { + "uninited", + "inited", + "connected" + }; + + return stateStr[socketState_]; +} } // namespace OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/websocket/websocket_client.h b/tooling/client/websocket/websocket_client.h index 56772e03..3fb7f6bb 100644 --- a/tooling/client/websocket/websocket_client.h +++ b/tooling/client/websocket/websocket_client.h @@ -43,7 +43,7 @@ public: WebsocketClient() = default; ~WebsocketClient() = default; bool InitToolchainWebSocketForPort(int port, uint32_t timeoutLimit = 5); - bool InitToolchainWebSocketForSockName(const std::string &sockName, uint32_t timeoutLimit = 0); + bool InitToolchainWebSocketForSockName(const std::string &sockName, uint32_t timeoutLimit = 5); bool ClientSendWSUpgradeReq(); bool ClientRecvWSUpgradeRsp(); bool ClientSendReq(const std::string &message); @@ -56,6 +56,7 @@ public: void Close(); bool SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit); bool IsConnected(); + std::string GetSocketStateString(); private: int32_t client_ {-1}; -- Gitee From 9a0d402609e6dd7466fd23b182ac7128259916dd Mon Sep 17 00:00:00 2001 From: yanpeng Date: Tue, 24 Oct 2023 16:41:13 +0800 Subject: [PATCH 2/3] client support multi-sessions Signed-off-by: yanpeng --- tooling/client/ark_cli/main.cpp | 4 ++-- tooling/client/domain/debugger_client.cpp | 10 +++++----- tooling/client/domain/heapprofiler_client.cpp | 6 +++--- tooling/client/domain/profiler_client.cpp | 4 ++-- tooling/client/domain/runtime_client.cpp | 6 +++--- tooling/client/domain/test_client.cpp | 3 ++- tooling/client/domain/test_client.h | 11 +++++++---- tooling/client/manager/breakpoint_manager.cpp | 2 +- tooling/client/manager/domain_manager.cpp | 4 ++-- tooling/client/manager/domain_manager.h | 10 +++++----- tooling/client/manager/stack_manager.cpp | 2 +- tooling/client/session/session.cpp | 13 ++++++------- tooling/client/session/session.h | 10 +++++----- tooling/client/utils/cli_command.cpp | 17 +++++++++-------- tooling/client/utils/cli_command.h | 2 +- 15 files changed, 54 insertions(+), 50 deletions(-) diff --git a/tooling/client/ark_cli/main.cpp b/tooling/client/ark_cli/main.cpp index d78b4f44..76598f21 100644 --- a/tooling/client/ark_cli/main.cpp +++ b/tooling/client/ark_cli/main.cpp @@ -22,7 +22,7 @@ #include #include "tooling/client/utils/cli_command.h" -#include "session/session.h" +#include "tooling/client/session/session.h" #include "manager/message_manager.h" namespace OHOS::ArkCompiler::Toolchain { @@ -128,7 +128,7 @@ void SocketOnMessage([[maybe_unused]] uv_async_t *handle) uint32_t sessionId = 0; std::string message; while (MessageManager::getInstance().MessagePop(sessionId, message)) { - Session* session = SessionManager::getInstance().GetSessionById(sessionId); + Session *session = SessionManager::getInstance().GetSessionById(sessionId); if (session == nullptr) { LOGE("arkdb get session by id %{public}u failed", sessionId); continue; diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp index fc4af54c..376b3d56 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -21,7 +21,7 @@ #include "tooling/client/manager/breakpoint_manager.h" #include "tooling/client/manager/stack_manager.h" #include "tooling/base/pt_json.h" -#include "session/session.h" +#include "tooling/client/session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { @@ -58,11 +58,11 @@ bool DebuggerClient::DispatcherCmd(const std::string &cmd) auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end()) { entry->second(); - LOGI("DebuggerClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + LOGI("DebuggerClient DispatcherCmd cmd: %{public}s", cmd.c_str()); return true; } - LOGI("DebuggerClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("unknown command: %{public}s", cmd.c_str()); return false; } @@ -354,7 +354,7 @@ void DebuggerClient::RecvReply(std::unique_ptr json) std::string breakpointId; ret = result->GetString("breakpointId", &breakpointId); if (ret == Result::SUCCESS) { - Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); BreakPointManager& breakpoint = session->GetBreakPointManager(); breakpoint.Createbreaklocation(std::move(json)); } @@ -393,7 +393,7 @@ void DebuggerClient::PausedReply(const std::unique_ptr json) data.emplace(i + 1, std::move(callFrameInfo)); } - Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); StackManager& stackManager = session->GetStackManager(); stackManager.ClearCallFrame(); stackManager.SetCallFrames(std::move(data)); diff --git a/tooling/client/domain/heapprofiler_client.cpp b/tooling/client/domain/heapprofiler_client.cpp index 09ad0375..e730b623 100644 --- a/tooling/client/domain/heapprofiler_client.cpp +++ b/tooling/client/domain/heapprofiler_client.cpp @@ -16,7 +16,7 @@ #include "tooling/client/domain/heapprofiler_client.h" #include "common/log_wrapper.h" #include "tooling/client/utils/utils.h" -#include "session/session.h" +#include "tooling/client/session/session.h" #include #include @@ -43,11 +43,11 @@ bool HeapProfilerClient::DispatcherCmd(const std::string &cmd, const std::string auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end() && entry->second != nullptr) { entry->second(); - LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + LOGI("DispatcherCmd reqStr1: %{public}s", cmd.c_str()); return true; } - LOGI("DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("unknown command: %{public}s", cmd.c_str()); return false; } diff --git a/tooling/client/domain/profiler_client.cpp b/tooling/client/domain/profiler_client.cpp index 9cdf93da..6221d946 100644 --- a/tooling/client/domain/profiler_client.cpp +++ b/tooling/client/domain/profiler_client.cpp @@ -17,7 +17,7 @@ #include "tooling/base/pt_types.h" #include "common/log_wrapper.h" #include "tooling/client/utils/utils.h" -#include "session/session.h" +#include "tooling/client/session/session.h" #include #include @@ -43,7 +43,7 @@ bool ProfilerClient::DispatcherCmd(const std::string &cmd) return false; } entry->second(); - LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + LOGI("DispatcherCmd cmd: %{public}s", cmd.c_str()); return true; } diff --git a/tooling/client/domain/runtime_client.cpp b/tooling/client/domain/runtime_client.cpp index 23bea9e7..33ca8e51 100644 --- a/tooling/client/domain/runtime_client.cpp +++ b/tooling/client/domain/runtime_client.cpp @@ -18,7 +18,7 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/variable_manager.h" #include "tooling/base/pt_json.h" -#include "session/session.h" +#include "tooling/client/session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { @@ -36,7 +36,7 @@ bool RuntimeClient::DispatcherCmd(const std::string &cmd) auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end()) { entry->second(); - LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", cmd.c_str()); return true; } else { LOGI("Unknown commond: %{public}s", cmd.c_str()); @@ -246,7 +246,7 @@ void RuntimeClient::HandleGetProperties(std::unique_ptr json, const int return; } - Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); StackManager &stackManager = session->GetStackManager(); VariableManager &variableManager = session->GetVariableManager(); std::map> treeInfo = stackManager.GetScopeChainInfo(); diff --git a/tooling/client/domain/test_client.cpp b/tooling/client/domain/test_client.cpp index d6c831cf..40439be0 100644 --- a/tooling/client/domain/test_client.cpp +++ b/tooling/client/domain/test_client.cpp @@ -18,6 +18,7 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/variable_manager.h" #include "tooling/base/pt_json.h" +#include "tooling/client/session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { @@ -31,7 +32,7 @@ bool TestClient::DispatcherCmd(const std::string &cmd) auto entry = dispatcherTable.find(cmd); if (entry != dispatcherTable.end()) { entry->second(); - LOGI("TestClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + LOGI("TestClient DispatcherCmd cmd: %{public}s", cmd.c_str()); return true; } else { LOGI("Unknown commond: %{public}s", cmd.c_str()); diff --git a/tooling/client/domain/test_client.h b/tooling/client/domain/test_client.h index c46b6667..6a768730 100644 --- a/tooling/client/domain/test_client.h +++ b/tooling/client/domain/test_client.h @@ -26,12 +26,15 @@ using Result = panda::ecmascript::tooling::Result; namespace OHOS::ArkCompiler::Toolchain { class TestClient final { public: - TestClient() = default; + TestClient(uint32_t sessionId) : sessionId_(sessionId) {} ~TestClient() = default; - bool DispatcherCmd(int id, const std::string &cmd, std::string *reqStr); - std::string SuccessCommand(int id); - std::string FailCommand(int id); + bool DispatcherCmd(const std::string &cmd); + int SuccessCommand(); + int FailCommand(); + +private: + uint32_t sessionId_; }; } // OHOS::ArkCompiler::Toolchain #endif // ECMASCRIPT_TOOLING_CLIENT_DOMAIN_TEST_CLIENT_H \ No newline at end of file diff --git a/tooling/client/manager/breakpoint_manager.cpp b/tooling/client/manager/breakpoint_manager.cpp index 5878635c..c143ef6a 100644 --- a/tooling/client/manager/breakpoint_manager.cpp +++ b/tooling/client/manager/breakpoint_manager.cpp @@ -17,7 +17,7 @@ #include "common/log_wrapper.h" #include "tooling/client/utils/utils.h" -#include "session/session.h" +#include "tooling/client/session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; using Result = panda::ecmascript::tooling::Result; diff --git a/tooling/client/manager/domain_manager.cpp b/tooling/client/manager/domain_manager.cpp index f4f0cdfe..92464890 100644 --- a/tooling/client/manager/domain_manager.cpp +++ b/tooling/client/manager/domain_manager.cpp @@ -18,14 +18,14 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/breakpoint_manager.h" #include "tooling/base/pt_json.h" -#include "session/session.h" +#include "tooling/client/session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; using Result = panda::ecmascript::tooling::Result; namespace OHOS::ArkCompiler::Toolchain { DomainManager::DomainManager(uint32_t sessionId) : sessionId_(sessionId), heapProfilerClient_(sessionId), profilerClient_(sessionId), - debuggerClient_(sessionId), runtimeClient_(sessionId) + debuggerClient_(sessionId), runtimeClient_(sessionId), testClient_(sessionId) { } diff --git a/tooling/client/manager/domain_manager.h b/tooling/client/manager/domain_manager.h index 3d3aaafb..893a2fe3 100644 --- a/tooling/client/manager/domain_manager.h +++ b/tooling/client/manager/domain_manager.h @@ -81,11 +81,11 @@ public: private: [[maybe_unused]] uint32_t sessionId_; - HeapProfilerClient heapProfilerClient_ {}; - ProfilerClient profilerClient_ {}; - DebuggerClient debuggerClient_ {}; - RuntimeClient runtimeClient_ {}; - TestClient testClient_ {}; + HeapProfilerClient heapProfilerClient_; + ProfilerClient profilerClient_; + DebuggerClient debuggerClient_; + RuntimeClient runtimeClient_; + TestClient testClient_; std::map idDomainMap_ {}; }; } // OHOS::ArkCompiler::Toolchain diff --git a/tooling/client/manager/stack_manager.cpp b/tooling/client/manager/stack_manager.cpp index 3468da22..a9940cb5 100644 --- a/tooling/client/manager/stack_manager.cpp +++ b/tooling/client/manager/stack_manager.cpp @@ -15,7 +15,7 @@ #include "tooling/client/manager/stack_manager.h" #include "common/log_wrapper.h" -#include "session/session.h" +#include "tooling/client/session/session.h" namespace OHOS::ArkCompiler::Toolchain { void StackManager::SetCallFrames(std::map> callFrames) diff --git a/tooling/client/session/session.cpp b/tooling/client/session/session.cpp index 48b350aa..2f61ce37 100755 --- a/tooling/client/session/session.cpp +++ b/tooling/client/session/session.cpp @@ -13,13 +13,12 @@ * limitations under the License. */ -#include "session/session.h" +#include "tooling/client/session/session.h" #include "common/log_wrapper.h" -#include "manager/breakpoint_manager.h" -#include "manager/message_manager.h" -#include "pt_json.h" -#include "utils/utils.h" +#include "tooling/client/manager/message_manager.h" +#include "tooling/base/pt_json.h" +#include "tooling/client/utils/utils.h" #include @@ -139,7 +138,7 @@ int SessionManager::CreateDefaultSession(std::string sockInfo) int SessionManager::DelSessionById(uint32_t sessionId) { - Session* session = GetSessionById(sessionId); + Session *session = GetSessionById(sessionId); if (session == nullptr) { return -1; } @@ -170,7 +169,7 @@ int SessionManager::SessionList() int SessionManager::SessionSwitch(uint32_t sessionId) { - Session* session = GetSessionById(sessionId); + Session *session = GetSessionById(sessionId); if (session == nullptr) { return -1; } diff --git a/tooling/client/session/session.h b/tooling/client/session/session.h index 0c889fe4..19137518 100755 --- a/tooling/client/session/session.h +++ b/tooling/client/session/session.h @@ -24,11 +24,11 @@ #include #include -#include "manager/domain_manager.h" -#include "manager/breakpoint_manager.h" -#include "manager/stack_manager.h" -#include "manager/variable_manager.h" -#include "websocket/websocket_client.h" +#include "tooling/client/manager/domain_manager.h" +#include "tooling/client/manager/breakpoint_manager.h" +#include "tooling/client/manager/stack_manager.h" +#include "tooling/client/manager/variable_manager.h" +#include "tooling/client/websocket/websocket_client.h" namespace OHOS::ArkCompiler::Toolchain { using CmdForAllCB = std::function; diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 3ce9c2a3..2ce82ff6 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -25,7 +25,7 @@ #include "tooling/client/manager/domain_manager.h" #include "tooling/client/manager/stack_manager.h" #include "tooling/client/manager/variable_manager.h" -#include "session/session.h" +#include "tooling/client/session/session.h" namespace OHOS::ArkCompiler::Toolchain { const std::string HELP_MSG = "usage: \n" @@ -237,7 +237,7 @@ ErrCode CliCommand::HeapProfilerCommand(const std::string &cmd) ErrCode CliCommand::CpuProfileCommand(const std::string &cmd) { std::cout << "exe success, cmd is " << cmd << std::endl; - Session* session = SessionManager::getInstance().GetSessionById(sessionId_); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); DomainManager &domainManager = session->GetDomainManager(); ProfilerClient &profilerClient = domainManager.GetProfilerClient(); ProfilerSingleton &pro = session->GetProfilerSingleton(); @@ -251,7 +251,7 @@ ErrCode CliCommand::CpuProfileCommand(const std::string &cmd) if (cmd == "cpuprofile-stop" && GetArgList().size() == 1) { pro.SetAddress(GetArgList()[0]); } - bool result = profilerClient->DispatcherCmd(cmd); + bool result = profilerClient.DispatcherCmd(cmd); return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL; } @@ -279,7 +279,7 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd) } if (cmd == "step-into" || cmd == "step-out" || cmd == "step-over") { - RuntimeClient &runtimeClient = session->GetDomainManager.GetRuntimeClient(); + RuntimeClient &runtimeClient = session->GetDomainManager().GetRuntimeClient(); runtimeClient.SetIsInitializeTree(true); } @@ -300,8 +300,8 @@ ErrCode CliCommand::RuntimeCommand(const std::string &cmd) { std::cout << "exe success, cmd is " << cmd << std::endl; bool result = false; - Session* session = SessionManager::getInstance().GetSessionById(sessionId_); - RuntimeClient &runtimeClient = session->GetDomainManager.GetRuntimeClient(); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + RuntimeClient &runtimeClient = session->GetDomainManager().GetRuntimeClient(); if (cmd == "print" && GetArgList().size() == 1) { runtimeClient.SetIsInitializeTree(false); @@ -310,7 +310,7 @@ ErrCode CliCommand::RuntimeCommand(const std::string &cmd) runtimeClient.SetObjectId(std::to_string(objectId)); } - result = runtimeClient->DispatcherCmd(cmd); + result = runtimeClient.DispatcherCmd(cmd); if (result) { runtimeClient.SetObjectId("0"); } else { @@ -377,7 +377,8 @@ ErrCode CliCommand::SessionSwitchCommand([[maybe_unused]] const std::string &cmd ErrCode CliCommand::TestCommand(const std::string &cmd) { if (cmd == "success" || cmd == "fail") { - TestClient &testClient = domainManager_.GetTestClient(); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + TestClient &testClient = session->GetDomainManager().GetTestClient(); testClient.DispatcherCmd(cmd); } else { return ErrCode::ERR_FAIL; diff --git a/tooling/client/utils/cli_command.h b/tooling/client/utils/cli_command.h index a06e7a21..5055173d 100644 --- a/tooling/client/utils/cli_command.h +++ b/tooling/client/utils/cli_command.h @@ -27,7 +27,7 @@ #include "tooling/client/manager/domain_manager.h" #include "tooling/client/utils/utils.h" #include "tooling/client/websocket/websocket_client.h" -#include "session/session.h" +#include "tooling/client/session/session.h" namespace OHOS::ArkCompiler::Toolchain { using StrPair = std::pair; -- Gitee From a30e98242c7889dc302cae34e404414ea10fb59e Mon Sep 17 00:00:00 2001 From: yanpeng Date: Tue, 24 Oct 2023 20:19:10 +0800 Subject: [PATCH 3/3] The development tool client supports source code display, watch expression, and multi-session Signed-off-by: yanpeng --- tooling/client/BUILD.gn | 2 + tooling/client/ark_cli/main.cpp | 2 +- tooling/client/domain/debugger_client.cpp | 31 +- tooling/client/domain/runtime_client.cpp | 5 + tooling/client/manager/breakpoint_manager.cpp | 2 +- tooling/client/manager/domain_manager.cpp | 4 + tooling/client/manager/source_manager.cpp | 274 ++++++++++++++++++ tooling/client/manager/source_manager.h | 55 ++++ tooling/client/manager/watch_manager.cpp | 227 +++++++++++++++ tooling/client/manager/watch_manager.h | 61 ++++ tooling/client/session/session.cpp | 2 +- tooling/client/session/session.h | 14 + tooling/client/utils/cli_command.cpp | 28 ++ 13 files changed, 702 insertions(+), 5 deletions(-) create mode 100755 tooling/client/manager/source_manager.cpp create mode 100755 tooling/client/manager/source_manager.h create mode 100755 tooling/client/manager/watch_manager.cpp create mode 100755 tooling/client/manager/watch_manager.h diff --git a/tooling/client/BUILD.gn b/tooling/client/BUILD.gn index e87bfff8..c01354cc 100644 --- a/tooling/client/BUILD.gn +++ b/tooling/client/BUILD.gn @@ -36,8 +36,10 @@ ohos_source_set("libark_client_set") { "domain/test_client.cpp", "manager/breakpoint_manager.cpp", "manager/domain_manager.cpp", + "manager/source_manager.cpp", "manager/stack_manager.cpp", "manager/variable_manager.cpp", + "manager/watch_manager.cpp", "session/session.cpp", "utils/cli_command.cpp", "utils/utils.cpp", diff --git a/tooling/client/ark_cli/main.cpp b/tooling/client/ark_cli/main.cpp index 76598f21..b6b3ea08 100644 --- a/tooling/client/ark_cli/main.cpp +++ b/tooling/client/ark_cli/main.cpp @@ -79,7 +79,7 @@ void InputOnMessage(uv_async_t *handle) } else { cliCmdStr.erase(cliCmdStr.begin()); SessionManager::getInstance().CmdForAllSessions(std::bind(InputMessageInSession, std::placeholders::_1, - cliCmdStr)); + cliCmdStr)); } } else { uint32_t sessionId = SessionManager::getInstance().GetCurrentSessionId(); diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp index 376b3d56..2b08b9c7 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -19,6 +19,7 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/breakpoint_manager.h" +#include "tooling/client/manager/source_manager.h" #include "tooling/client/manager/stack_manager.h" #include "tooling/base/pt_json.h" #include "tooling/client/session/session.h" @@ -307,7 +308,7 @@ void DebuggerClient::AddBreakPointInfo(const std::string& url, const int& lineNu { BreakPointInfo breakPointInfo; breakPointInfo.url = url; - breakPointInfo.lineNumber = lineNumber; + breakPointInfo.lineNumber = lineNumber - 1; breakPointInfo.columnNumber = columnNumber; breakPointInfoList_.emplace_back(breakPointInfo); } @@ -333,6 +334,10 @@ void DebuggerClient::RecvReply(std::unique_ptr json) LOGE("arkdb: find method error"); } + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + SourceManager &sourceManager = session->GetSourceManager(); + WatchManager &watchManager = session->GetWatchManager(); + std::string::size_type length = wholeMethod.length(); std::string::size_type indexPoint = 0; indexPoint = wholeMethod.find_first_of('.', 0); @@ -340,6 +345,9 @@ void DebuggerClient::RecvReply(std::unique_ptr json) if (method == "paused") { PausedReply(std::move(json)); return; + } else if (method == "scriptParsed") { + sourceManager.EnableReply(std::move(json)); + return; } else { LOGI("arkdb: Debugger reply is: %{public}s", json->Stringify().c_str()); } @@ -350,13 +358,27 @@ void DebuggerClient::RecvReply(std::unique_ptr json) LOGE("arkdb: find result error"); return; } + int32_t id; + ret = json->GetInt("id", &id); + if (ret == Result::SUCCESS) { + std::string scriptSource; + ret = result->GetString("scriptSource", &scriptSource); + if (ret == Result::SUCCESS) { + sourceManager.SetFileSource(id, scriptSource); + return; + } + } std::string breakpointId; ret = result->GetString("breakpointId", &breakpointId); if (ret == Result::SUCCESS) { - Session *session = SessionManager::getInstance().GetSessionById(sessionId_); BreakPointManager& breakpoint = session->GetBreakPointManager(); breakpoint.Createbreaklocation(std::move(json)); + sourceManager.GetDebugInfo(std::move(result)); + return; + } + if (watchManager.ShowWatchInfo(std::move(json), id)) { + return; } } @@ -395,7 +417,12 @@ void DebuggerClient::PausedReply(const std::unique_ptr json) Session *session = SessionManager::getInstance().GetSessionById(sessionId_); StackManager& stackManager = session->GetStackManager(); + SourceManager &sourceManager = session->GetSourceManager(); + WatchManager &watchManager = session->GetWatchManager(); stackManager.ClearCallFrame(); stackManager.SetCallFrames(std::move(data)); + sourceManager.GetDebugSources(callFrames->Get(0)); + watchManager.RequeWatchInfo(callFrames->Get(0)); + watchManager.DebugTrueState(); } } // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/domain/runtime_client.cpp b/tooling/client/domain/runtime_client.cpp index 33ca8e51..910e2cf6 100644 --- a/tooling/client/domain/runtime_client.cpp +++ b/tooling/client/domain/runtime_client.cpp @@ -198,6 +198,11 @@ void RuntimeClient::RecvReply(std::unique_ptr json) HandleGetProperties(std::move(json), replyId); } else { LOGI("arkdb: Runtime replay message is %{public}s", json->Stringify().c_str()); + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + WatchManager &watchManager = session->GetWatchManager(); + if (watchManager.ShowWatchResult2(std::move(json))) { + return; + } } } diff --git a/tooling/client/manager/breakpoint_manager.cpp b/tooling/client/manager/breakpoint_manager.cpp index c143ef6a..aba3e526 100644 --- a/tooling/client/manager/breakpoint_manager.cpp +++ b/tooling/client/manager/breakpoint_manager.cpp @@ -63,7 +63,7 @@ void BreakPointManager::Show() int size = breaklist_.size(); for (int i = 0; i < size; i++) { std::cout << (i + 1) << ':' << " url:" << breaklist_[i].url; - std::cout << " lineNumber:" << breaklist_[i].lineNumber + std::cout << " lineNumber:" << std::atoi(breaklist_[i].lineNumber.c_str()) + 1 << " columnNumber:" << breaklist_[i].columnNumber << std::endl; } } diff --git a/tooling/client/manager/domain_manager.cpp b/tooling/client/manager/domain_manager.cpp index 92464890..52dcafb3 100644 --- a/tooling/client/manager/domain_manager.cpp +++ b/tooling/client/manager/domain_manager.cpp @@ -33,6 +33,7 @@ void DomainManager::DispatcherReply(char* msg) { std::string decMessage = std::string(msg); std::unique_ptr json = PtJson::Parse(decMessage); + std::unique_ptr watchJson = PtJson::Parse(decMessage); if (json == nullptr) { LOGE("json parse error"); return; @@ -52,6 +53,9 @@ void DomainManager::DispatcherReply(char* msg) domain = GetDomainById(id); RemoveDomainById(id); } + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + WatchManager &watchManager = session->GetWatchManager(); + watchManager.DebugFalseState(); std::string wholeMethod; ret = json->GetString("method", &wholeMethod); diff --git a/tooling/client/manager/source_manager.cpp b/tooling/client/manager/source_manager.cpp new file mode 100755 index 00000000..c728d6d1 --- /dev/null +++ b/tooling/client/manager/source_manager.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tooling/client/manager/source_manager.h" + +#include "common/log_wrapper.h" +#include "tooling/client/session/session.h" + +using PtJson = panda::ecmascript::tooling::PtJson; +using Result = panda::ecmascript::tooling::Result; +namespace OHOS::ArkCompiler::Toolchain { +void SourceManager::SendRequeSource(int scriptId) +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + scriptIdMap_.emplace(std::make_pair(id, scriptId)); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Debugger.getScriptSource"); + + std::unique_ptr params = PtJson::CreateObject(); + params->Add("scriptId", std::to_string(scriptId).c_str()); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return; +} + +void SourceManager::EnableReply(const std::unique_ptr json) +{ + if (json == nullptr) { + LOGE("arkdb: json parse error"); + return; + } + + if (!json->IsObject()) { + LOGE("arkdb: json parse format error"); + json->ReleaseRoot(); + return; + } + + std::unique_ptr params; + Result ret = json->GetObject("params", ¶ms); + if (ret != Result::SUCCESS) { + LOGE("arkdb: find params error"); + return; + } + + std::string scriptIdStr; + ret = params->GetString("scriptId", &scriptIdStr); + if (ret != Result::SUCCESS) { + LOGE("arkdb: find scriptId error"); + return; + } + + std::string fileName; + ret = params->GetString("url", &fileName); + if (ret != Result::SUCCESS) { + LOGE("arkdb: find fileName error"); + return; + } + int scriptId = std::atoi(scriptIdStr.c_str()); + SetFileName(scriptId, fileName); + SendRequeSource(scriptId); + return; +} + +void SourceManager::SetFileName(int scriptId, const std::string& fileName) +{ + fileSource_.insert(std::make_pair(scriptId, std::make_pair(fileName, std::vector{}))); + return; +} + +void SourceManager::GetFileName() +{ + for (auto it = fileSource_.begin(); it != fileSource_.end(); it++) { + std::cout << "scriptID : " << it->first; + std::cout << " fileName : " << it->second.first <second; + + auto it = fileSource_.find(scriptId); + if (it != fileSource_.end()) { + int startPos = 0; + uint endPos = fileSource.find("\r\n"); + while (endPos != std::string::npos) { + std::string line = fileSource.substr(startPos, endPos - startPos); + it->second.second.push_back(line); + startPos = endPos + 2; // ignore "\r\n" + endPos = fileSource.find("\r\n", startPos); + } + it->second.second.push_back(fileSource.substr(startPos)); + } + return; +} + +std::vector SourceManager::GetFileSource(int scriptId) +{ + int linNum = 0; + auto it = fileSource_.find(scriptId); + if (it != fileSource_.end()) { + std::cout << "fileSource : " <second.second) { + std::cout << ++linNum << " " << value << std::endl; + } + return it->second.second; + } + return std::vector{}; +} + +void SourceManager::GetDebugSources(const std::unique_ptr json) +{ + std::string funcName; + Result ret; + ret = json->GetString("functionName", &funcName); + if (ret != Result::SUCCESS) { + LOGE("arkdb: get functionName error"); + return; + } + + std::unique_ptr location; + ret = json->GetObject("location", &location); + if (ret != Result::SUCCESS) { + LOGE("arkdb: get location error"); + return; + } + + std::string scriptIdStr; + ret = location->GetString("scriptId", &scriptIdStr); + if (ret != Result::SUCCESS) { + LOGE("arkdb: get scriptId error"); + return; + } + scriptId_ = std::atoi(scriptIdStr.c_str()); + + ret = location->GetInt("lineNumber", &debugLineNum_); + if (ret != Result::SUCCESS) { + LOGE("arkdb: get lineNumber error"); + return; + } + + LOGE("arkdb: callFrames : funcName %{public}s, scriptid %{public}s, lineNum %{public}d", + funcName.c_str(), scriptIdStr.c_str(), debugLineNum_); + auto it = fileSource_.find(scriptId_); + if (it != fileSource_.end()) { + std::cout << debugLineNum_ + 1 << " " << it->second.second[debugLineNum_] << std::endl; + std::cout << ">>> "; + fflush(stdout); + } + return; +} + +void SourceManager::ListSource(int startLine, int endLine) +{ + const int STATR_LINE_OFFSET = 6; + const int END_LINE_OFFSET = 4; + const int END_LINE = 10; + if (startLine == 0 && endLine == 0) { + auto it = fileSource_.find(scriptId_); + if (it == fileSource_.end()) { + LOGE("arkdb: get file source error"); + return; + } + int showLine = (debugLineNum_ + 1) - STATR_LINE_OFFSET; + if (showLine < 0) { + showLine = 0; + endLine = END_LINE; + } else { + endLine = debugLineNum_ + END_LINE_OFFSET; + } + for (; showLine <= endLine; showLine++) { + std::cout << showLine + 1 << " " << it->second.second[showLine] << std::endl; + } + } else if (startLine != 0 && endLine == 0) { + auto it = fileSource_.find(scriptId_); + if (it == fileSource_.end()) { + LOGE("arkdb: get file source error"); + return; + } + if (startLine > static_cast(it->second.second.size())) { + return; + } + int showLine = startLine - STATR_LINE_OFFSET; + if (showLine < 0) { + showLine = 0; + endLine = END_LINE; + } else { + endLine = startLine + END_LINE_OFFSET; + } + for (; showLine < endLine; showLine++) { + std::cout << showLine + 1 << " " << it->second.second[showLine] << std::endl; + } + } else if (startLine != 0 && endLine != 0) { + auto it = fileSource_.find(scriptId_); + if (it == fileSource_.end()) { + LOGE("arkdb: get file source error"); + return; + } + if (startLine > static_cast(it->second.second.size()) || + endLine > static_cast(it->second.second.size())) { + return; + } + for (int showLine = startLine - 1; showLine < endLine; showLine++) { + std::cout << showLine + 1 << " " << it->second.second[showLine] << std::endl; + } + } +} + +void SourceManager::GetListSource(std::string lineNum) +{ + if (lineNum != "") { + size_t found = lineNum.find(","); + if (found != std::string::npos) { + std::string startLine = lineNum.substr(0, found); + std::string endLine = lineNum.substr(found + 1); + ListSource(std::atoi(startLine.c_str()), std::atoi(endLine.c_str())); + } else { + ListSource(std::atoi(lineNum.c_str()), 0); + } + } else { + ListSource(0, 0); + } + return; +} + +void SourceManager::GetDebugInfo(const std::unique_ptr json) +{ + Result ret; + std::unique_ptr locations; + ret = json->GetArray("locations", &locations); + if (ret != Result::SUCCESS) { + LOGE("json parse locations error"); + return; + } + std::string scriptId; + ret = locations->Get(0)->GetString("scriptId", &scriptId); + if (ret != Result::SUCCESS) { + LOGE("json parse scriptId error"); + return; + } + scriptId_ = std::atoi(scriptId.c_str()); + ret = locations->Get(0)->GetInt("lineNumber", &debugLineNum_); + if (ret != Result::SUCCESS) { + LOGE("json parse lineNumber error"); + return; + } + return; +} +} \ No newline at end of file diff --git a/tooling/client/manager/source_manager.h b/tooling/client/manager/source_manager.h new file mode 100755 index 00000000..1eba50e2 --- /dev/null +++ b/tooling/client/manager/source_manager.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ECMASCRIPT_TOOLING_CLIENT_MANAGER_SOURCE_MANAGER_H +#define ECMASCRIPT_TOOLING_CLIENT_MANAGER_SOURCE_MANAGER_H + +#include +#include +#include +#include +#include + +#include "tooling/base/pt_json.h" +#include "tooling/base/pt_types.h" + +namespace OHOS::ArkCompiler::Toolchain { +using PtJson = panda::ecmascript::tooling::PtJson; +using Result = panda::ecmascript::tooling::Result; +class SourceManager { +public: + SourceManager(int32_t sessionId) : sessionId_(sessionId) {} + + void SendRequeSource(int scriptId); + void EnableReply(const std::unique_ptr json); + void GetFileName(); + void SetFileName(int scriptId, const std::string& fileName); + void SetFileSource(int scriptIdIndex, const std::string& fileSource); + std::vector GetFileSource(int scriptId); + void GetDebugSources(const std::unique_ptr json); + void ListSource(int startLine, int endLine); + void GetListSource(std::string lineNum); + void GetDebugInfo(const std::unique_ptr json); + +private: + [[maybe_unused]] int32_t sessionId_; + int32_t scriptId_; + int32_t debugLineNum_; + std::unordered_map scriptIdMap_ {}; + std::unordered_map>> fileSource_ {}; + SourceManager(const SourceManager&) = delete; + SourceManager& operator=(const SourceManager&) = delete; +}; +} // OHOS::ArkCompiler::Toolchain +#endif \ No newline at end of file diff --git a/tooling/client/manager/watch_manager.cpp b/tooling/client/manager/watch_manager.cpp new file mode 100755 index 00000000..5ceedeab --- /dev/null +++ b/tooling/client/manager/watch_manager.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tooling/client/manager/watch_manager.h" + +#include "common/log_wrapper.h" +#include "tooling/client/session/session.h" + +using PtJson = panda::ecmascript::tooling::PtJson; +using Result = panda::ecmascript::tooling::Result; +namespace OHOS::ArkCompiler::Toolchain { +WatchManager::WatchManager(uint32_t sessionId) + : sessionId_(sessionId), runtimeClient_{sessionId} +{ +} + +void WatchManager::SendRequeWatch(const int32_t &watchInfoIndex, const std::string &callFrameId) +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + watchInfoMap_.emplace(id, watchInfoList_[watchInfoIndex]); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Debugger.evaluateOnCallFrame"); + + std::unique_ptr params = PtJson::CreateObject(); + params->Add("callFrameId", callFrameId.c_str()); + params->Add("expression", watchInfoList_[watchInfoIndex].c_str()); + params->Add("objectGroup", "watch-group"); + params->Add("includeCommandLineAPI", false); + params->Add("silent", true); + params->Add("returnByValue", false); + params->Add("generatePreview", false); + params->Add("throwOnSideEffect", false); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + inputRowFlag_++; + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return; +} + +void WatchManager::RequeWatchInfo(const std::unique_ptr &json) +{ + Result ret; + ret = json->GetString("callFrameId", &callFrameId_); + if (ret != Result::SUCCESS) { + LOGE("arkdb: find callFrameId error"); + return; + } + for (uint i = 0; i < watchInfoList_.size(); i++) { + SendRequeWatch(i, callFrameId_); + } +} + +std::string WatchManager::GetCallFrameId() +{ + return callFrameId_; +} + +int WatchManager::GetWatchInfoSize() +{ + return watchInfoList_.size(); +} + +void WatchManager::AddWatchInfo(const std::string& watchInfo) +{ + watchInfoList_.emplace_back(watchInfo); +} + +bool WatchManager::GetDebugState() +{ + return IsDebug_; +} +void WatchManager::DebugFalseState() +{ + IsDebug_ = false; +} +void WatchManager::DebugTrueState() +{ + IsDebug_ = true; +} + +bool WatchManager::ShowWatchInfo(std::unique_ptr json, int32_t id) +{ + Result ret; + std::unique_ptr result; + ret = json->GetObject("result", &result); + if (ret != Result::SUCCESS) { + LOGE("json parse result error"); + return false; + } + std::unique_ptr watchResult; + ret = result->GetObject("result", &watchResult); + if (ret != Result::SUCCESS) { + LOGE("json parse result error"); + return false; + } + if (!ShowWatchResult(std::move(watchResult), id)) { + return false; + } + inputRowFlag_--; + if (inputRowFlag_ == 0) { + std::cout << ">>> "; + fflush(stdout); + isShowWatchInfo_ = true; + } + return true; +} +bool WatchManager::ShowWatchResult(std::unique_ptr result, int32_t id) +{ + Result ret; + std::string type; + std::string reqStr; + ret = result->GetString("type", &type); + if (ret != Result::SUCCESS) { + LOGE("json parse type error"); + return false; + } + if (inputRowFlag_ == GetWatchInfoSize() && isShowWatchInfo_) { + std::cout << "watch info :" << std::endl; + isShowWatchInfo_ = false; + } + if (type == "undefined") { + auto it = watchInfoMap_.find(id); + if (it == watchInfoMap_.end()) { + return false; + } + std::cout << " " << it->second << " = undefined" << std::endl; + } else if (type == "object") { + std::string objectId; + ret = result->GetString("objectId", &objectId); + if (ret != Result::SUCCESS) { + LOGE("json parse object error"); + return false; + } + auto it = watchInfoMap_.find(id); + if (it == watchInfoMap_.end()) { + return false; + } + watchName_ = it->second; + runtimeClient_.SetObjectId(objectId); + runtimeClient_.DispatcherCmd("print"); + inputRowFlag_++; + } else { + auto it = watchInfoMap_.find(id); + if (it == watchInfoMap_.end()) { + return false; + } + std::string description; + ret = result->GetString("description", &description); + if (ret != Result::SUCCESS) { + LOGE("json parse description error"); + return false; + } + std::cout << " " << it->second << " = " << description << std::endl; + } + DebugTrueState(); + return true; +} + +bool WatchManager::ShowWatchResult2(std::unique_ptr result) +{ + Result ret; + std::unique_ptr resultWatch; + ret = result->GetObject("result", &resultWatch); + if (ret != Result::SUCCESS) { + LOGE("json parse result error"); + return false; + } + std::unique_ptr watchResult; + ret = resultWatch->GetArray("result", &watchResult); + if (ret != Result::SUCCESS) { + LOGE("json parse result error"); + return false; + } + std::cout << " " << watchName_ << " = { "; + for (int32_t i = 0; i < watchResult->GetSize(); i++) { + std::string name; + ret = watchResult->Get(i)->GetString("name", &name); + if (ret != Result::SUCCESS) { + LOGE("json parse name error"); + continue; + } + std::unique_ptr value; + ret = watchResult->Get(i)->GetObject("value", &value); + if (ret != Result::SUCCESS) { + LOGE("json parse value error"); + continue; + } + std::string description; + ret = value->GetString("description", &description); + if (ret != Result::SUCCESS) { + LOGE("json parse description error"); + continue; + } + std::cout << name << " = " << description; + if (i < watchResult->GetSize() - 1) { + std::cout << ", "; + } + } + std::cout << " }" << std::endl; + inputRowFlag_--; + if (inputRowFlag_ == 0) { + std::cout << ">>> "; + fflush(stdout); + isShowWatchInfo_ = true; + } + DebugTrueState(); + return true; +} +} \ No newline at end of file diff --git a/tooling/client/manager/watch_manager.h b/tooling/client/manager/watch_manager.h new file mode 100755 index 00000000..018d8deb --- /dev/null +++ b/tooling/client/manager/watch_manager.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ECMASCRIPT_TOOLING_CLIENT_MANAGER_WATCH_MANAGER_H +#define ECMASCRIPT_TOOLING_CLIENT_MANAGER_WATCH_MANAGER_H + +#include +#include +#include +#include +#include + +#include "tooling/base/pt_json.h" +#include "tooling/base/pt_types.h" +#include "tooling/client/domain/runtime_client.h" + +namespace OHOS::ArkCompiler::Toolchain { +using PtJson = panda::ecmascript::tooling::PtJson; +using Result = panda::ecmascript::tooling::Result; +class WatchManager { +public: + explicit WatchManager(uint32_t sessionId); + ~WatchManager() = default; + + void SendRequeWatch(const int32_t &watchInfoIndex, const std::string &callFrameId); + void RequeWatchInfo(const std::unique_ptr &json); + void AddWatchInfo(const std::string& watchInfo); + + bool GetDebugState(); + void DebugFalseState(); + void DebugTrueState(); + bool ShowWatchInfo(std::unique_ptr json, int32_t id); + bool ShowWatchResult(std::unique_ptr result, int32_t id); + bool ShowWatchResult2(std::unique_ptr result); + std::string GetCallFrameId(); + int GetWatchInfoSize(); + +private: + [[maybe_unused]] int32_t sessionId_; + std::vector watchInfoList_; + std::unordered_map watchInfoMap_; + bool IsDebug_; + std::string callFrameId_; + std::string watchName_; + RuntimeClient runtimeClient_; + int inputRowFlag_; + bool isShowWatchInfo_ = true; +}; +} // OHOS::ArkCompiler::Toolchain +#endif \ No newline at end of file diff --git a/tooling/client/session/session.cpp b/tooling/client/session/session.cpp index 2f61ce37..5cd343fd 100755 --- a/tooling/client/session/session.cpp +++ b/tooling/client/session/session.cpp @@ -36,7 +36,7 @@ void SocketMessageThread(void *arg) Session::Session(uint32_t sessionId, std::string& sockInfo) : sessionId_(sessionId), sockInfo_(sockInfo), domainManager_(sessionId), breakpoint_(sessionId), - stackManager_(sessionId), variableManager_(sessionId) + stackManager_(sessionId), variableManager_(sessionId), sourceManager_{sessionId}, watchManager_{sessionId} { } diff --git a/tooling/client/session/session.h b/tooling/client/session/session.h index 19137518..16f336d3 100755 --- a/tooling/client/session/session.h +++ b/tooling/client/session/session.h @@ -26,8 +26,10 @@ #include "tooling/client/manager/domain_manager.h" #include "tooling/client/manager/breakpoint_manager.h" +#include "tooling/client/manager/source_manager.h" #include "tooling/client/manager/stack_manager.h" #include "tooling/client/manager/variable_manager.h" +#include "tooling/client/manager/watch_manager.h" #include "tooling/client/websocket/websocket_client.h" namespace OHOS::ArkCompiler::Toolchain { @@ -81,6 +83,16 @@ public: return variableManager_; } + SourceManager& GetSourceManager() + { + return sourceManager_; + } + + WatchManager& GetWatchManager() + { + return watchManager_; + } + ProfilerSingleton& GetProfilerSingleton() { return profiler_; @@ -107,6 +119,8 @@ private: StackManager stackManager_; VariableManager variableManager_; ProfilerSingleton profiler_; + SourceManager sourceManager_; + WatchManager watchManager_; }; constexpr uint32_t MAX_SESSION_NUM = 8; diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 2ce82ff6..75345986 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -262,6 +262,8 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd) Session *session = SessionManager::getInstance().GetSessionById(sessionId_); DebuggerClient &debuggerCli = session->GetDomainManager().GetDebuggerClient(); BreakPointManager &breakpoint = session->GetBreakPointManager(); + SourceManager &sourceManager = session->GetSourceManager(); + WatchManager &watchManager = session->GetWatchManager(); if (cmd == "display") { breakpoint.Show(); return ErrCode::ERR_OK; @@ -292,6 +294,32 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd) debuggerCli.AddBreakPointInfo(GetArgList()[0], std::stoi(GetArgList()[1])); } + if (cmd == "infosource") { + if (GetArgList().size() == 1) { + sourceManager.GetFileSource(std::atoi(GetArgList()[0].c_str())); + } else { + sourceManager.GetFileName(); + } + return ErrCode::ERR_OK; + } + + if (cmd == "list") { + if (GetArgList().size() == 1) { + sourceManager.GetListSource(GetArgList()[0]); + } else { + sourceManager.GetListSource(""); + } + return ErrCode::ERR_OK; + } + + if (cmd == "watch" && GetArgList().size() == 1) { + watchManager.AddWatchInfo(GetArgList()[0]); + if (watchManager.GetDebugState()) { + watchManager.SendRequeWatch(watchManager.GetWatchInfoSize() - 1, watchManager.GetCallFrameId()); + } + return ErrCode::ERR_OK; + } + result = debuggerCli.DispatcherCmd(cmd); return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL; } -- Gitee