diff --git a/tooling/client/BUILD.gn b/tooling/client/BUILD.gn index ba9921447ca40d2f56a25f4b804d5302918c4432..c01354cca21efcb5af4a867a5b05d9fbc5ccabce 100644 --- a/tooling/client/BUILD.gn +++ b/tooling/client/BUILD.gn @@ -36,8 +36,11 @@ 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", "websocket/websocket_client.cpp", diff --git a/tooling/client/ark_cli/main.cpp b/tooling/client/ark_cli/main.cpp index f3b7df10888b1bc01d72511375a27de79e480f4f..42380a4c6154fc38f60779738d9f7194b5ff7dbc 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 "tooling/client/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,31 @@ 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"); + std::string sockInfo(argv[1]); + if (SessionManager::getInstance().CreateDefaultSession(sockInfo)) { + LOGE("arkdb create default session failed"); return -1; } @@ -204,9 +165,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 cfb9eefbcb832c5548e14d60f5d3f408d92148d7..56b73e8f26c84de5ae91c325b7f2c7bf3bf2c513 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -19,55 +19,59 @@ #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" 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(); - LOGI("DebuggerClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + entry->second(); + LOGI("DebuggerClient DispatcherCmd cmd: %{public}s", cmd.c_str()); return true; } - *reqStr = "Unknown commond: " + cmd; - LOGI("DebuggerClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("unknown command: %{public}s", cmd.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 +81,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,155 +107,208 @@ 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) { BreakPointInfo breakPointInfo; breakPointInfo.url = url; - breakPointInfo.lineNumber = lineNumber; + breakPointInfo.lineNumber = lineNumber - 1; breakPointInfo.columnNumber = columnNumber; breakPointInfoList_.emplace_back(breakPointInfo); } @@ -261,14 +326,16 @@ void DebuggerClient::RecvReply(std::unique_ptr json) return; } - Result ret; std::string wholeMethod; std::string method; - ret = json->GetString("method", &wholeMethod); + Result ret = json->GetString("method", &wholeMethod); if (ret != Result::SUCCESS) { LOGE("arkdb: find method error"); } + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + SourceManager &sourceManager = session->GetSourceManager(); + std::string::size_type length = wholeMethod.length(); std::string::size_type indexPoint = 0; indexPoint = wholeMethod.find_first_of('.', 0); @@ -276,23 +343,13 @@ 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()); } - - std::unique_ptr result; - ret = json->GetObject("result", &result); - if (ret != Result::SUCCESS) { - LOGE("arkdb: find result error"); - return; - } - - std::string breakpointId; - ret = result->GetString("breakpointId", &breakpointId); - if (ret == Result::SUCCESS) { - BreakPointManager &breakpoint = BreakPointManager::GetInstance(); - breakpoint.Createbreaklocation(std::move(json)); - } + handleResponse(std::move(json)); } void DebuggerClient::PausedReply(const std::unique_ptr json) @@ -328,8 +385,49 @@ 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(); + SourceManager &sourceManager = session->GetSourceManager(); + WatchManager &watchManager = session->GetWatchManager(); stackManager.ClearCallFrame(); stackManager.SetCallFrames(std::move(data)); + sourceManager.GetDebugSources(callFrames->Get(0)); + watchManager.RequestWatchInfo(callFrames->Get(0)); + watchManager.DebugTrueState(); +} + +void DebuggerClient::handleResponse(std::unique_ptr json) +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + SourceManager &sourceManager = session->GetSourceManager(); + WatchManager &watchManager = session->GetWatchManager(); + BreakPointManager& breakpoint = session->GetBreakPointManager(); + std::unique_ptr result; + Result ret = json->GetObject("result", &result); + if (ret != Result::SUCCESS) { + 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) { + breakpoint.Createbreaklocation(std::move(json)); + sourceManager.GetDebugInfo(std::move(result)); + return; + } + if (watchManager.HandleWatchResult(std::move(json), id)) { + return; + } + return; } } // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/domain/debugger_client.h b/tooling/client/domain/debugger_client.h index 1864275e49a70df52d7b3525d8436b6d67919f7d..ddf03031da7aab696f627ff75318056cd3d8fa4c 100644 --- a/tooling/client/domain/debugger_client.h +++ b/tooling/client/domain/debugger_client.h @@ -31,41 +31,43 @@ 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); void PausedReply(const std::unique_ptr json); + void handleResponse(std::unique_ptr json); 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 61b622c5428b1446b7968f190ccee06763a1fda0..570c79d2081d5b7b39008f9dd520bf5354c3e05b 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 "tooling/client/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(); - LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + entry->second(); + LOGI("DispatcherCmd reqStr1: %{public}s", cmd.c_str()); return true; } - *reqStr = "Unknown commond: " + cmd; - LOGI("DispatcherCmd reqStr2: %{public}s", reqStr->c_str()); + LOGI("unknown command: %{public}s", cmd.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_ = "/data/Heap-" + std::string(date) + "T" + std::string(time) + ".heaptimeline"; + fileName_ = "/data/Heap-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" + std::string(time) + + ".heaptimeline"; std::cout << "heaptimeline file name is " << fileName_ << std::endl; } else { - fileName_ = "/data/Heap-" + std::string(date) + "T" + std::string(time) + ".heapsnapshot"; + fileName_ = "/data/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 bb4f99f03faf25314c48fc6355c4f60f4676bbbe..b107175678a29d12aacc511657c0c3c4e4245231 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 b5c4e073dd41c0ddba0f33436408b77718a5381a..b963312a597f86dcaf9c3d689369f4ff7bcf5ffc 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 "tooling/client/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(); - LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + entry->second(); + LOGI("DispatcherCmd cmd: %{public}s", cmd.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 = "/data/CPU-" + std::string(date) + "T" + std::string(time) + ".cpuprofile"; + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + ProfilerSingleton &pro = session->GetProfilerSingleton(); + std::string fileName = "/data/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()); @@ -177,7 +213,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 7f2ee833ab99e82bfb26631808902fb5eb89441a..5c1681b7dc11c9bcbf4e8390da167cd330a085c1 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 3731c4dd8384338e9a9ebea6234b5fd6d912582f..33ca8e51703c922a6bad16dae72c54acd2e65842 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 "tooling/client/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(); - LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + entry->second(); + LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", cmd.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 3d428c19f18df92c1cf565b0b365b62151130375..12e127054e6d259d4274fd438e2b9f611da2d4ae 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 663559417955d8113bc9da6d0f8546f55ac15f8b..40439be02704f895bc36afda79dad0af867b213d 100644 --- a/tooling/client/domain/test_client.cpp +++ b/tooling/client/domain/test_client.cpp @@ -18,47 +18,63 @@ #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 { -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(); - LOGI("TestClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str()); + entry->second(); + LOGI("TestClient DispatcherCmd cmd: %{public}s", cmd.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/domain/test_client.h b/tooling/client/domain/test_client.h index c46b6667535a1572ae66e6c7a0bb2c194360ee12..6a76873031713c9448819850f7a79409026218bf 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 77c95f1bf93495c22860bf66c31e1677d75a7184..8109d154552db9785c816d00760787ce7eede581 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 "tooling/client/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) { @@ -68,7 +63,7 @@ void BreakPointManager::Show() size_t size = breaklist_.size(); for (size_t 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/breakpoint_manager.h b/tooling/client/manager/breakpoint_manager.h index 115702b3c057ff99921fc66ab35017cdfec2db29..76958898c6292a2a8f5e54187a373ddf5e333e89 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 75a35546eb01954cd05ccd6321f10d20cdede254..24d59470c8fcdb50c39c21b8f6d2ff83ac1a3d3c 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 "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), testClient_(sessionId) +{ +} + void DomainManager::DispatcherReply(char* msg) { std::string decMessage = std::string(msg); @@ -45,6 +52,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/domain_manager.h b/tooling/client/manager/domain_manager.h index 0c6dc586b8ec63058f0e8a48da3600bf68b7ceea..893a2fe341e4b4f5643957caed42be233c4a3ec3 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,11 +80,12 @@ public: } private: - HeapProfilerClient heapProfilerClient_ {}; - ProfilerClient profilerClient_ {}; - DebuggerClient debuggerClient_ {}; - RuntimeClient runtimeClient_ {}; - TestClient testClient_ {}; + [[maybe_unused]] uint32_t sessionId_; + HeapProfilerClient heapProfilerClient_; + ProfilerClient profilerClient_; + DebuggerClient debuggerClient_; + RuntimeClient runtimeClient_; + TestClient testClient_; std::map idDomainMap_ {}; }; } // OHOS::ArkCompiler::Toolchain diff --git a/tooling/client/manager/message_manager.h b/tooling/client/manager/message_manager.h new file mode 100755 index 0000000000000000000000000000000000000000..028dced8c9e8d2fd7fa92f782c113f21a5bee01c --- /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, 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/source_manager.cpp b/tooling/client/manager/source_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..528e6a0598edac587dc006c387108d4f2131ad7e --- /dev/null +++ b/tooling/client/manager/source_manager.cpp @@ -0,0 +1,315 @@ +/* + * 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() && it->second.second.empty()) { + int startPos = 0; + std::string::size_type 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 + IGNOR_NEWLINE_FLAG; // 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 = 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::ListSourceCodeWithParameters(int startLine, int endLine) +{ + const int BLANK_LINE = std::numeric_limits::max(); + const int STATR_LINE_OFFSET = 6; + const int END_LINE_OFFSET = 4; + const int END_LINE = 10; + if (startLine != BLANK_LINE && endLine == BLANK_LINE) { + auto it = fileSource_.find(scriptId_); + if (it == fileSource_.end()) { + LOGE("arkdb: get file source error"); + return; + } + if (startLine >= static_cast(it->second.second.size()) + STATR_LINE_OFFSET || + startLine < 0) { + std::cout << "Line number out of range, this file has " << + static_cast(it->second.second.size()) << " lines" << std::endl; + return; + } + int showLine = startLine - STATR_LINE_OFFSET; + if (showLine < 0) { + showLine = 0; + endLine = END_LINE; + } else { + endLine = startLine + END_LINE_OFFSET; + } + if (endLine > static_cast(it->second.second.size())) { + endLine = static_cast(it->second.second.size()); + } + for (; showLine < endLine; showLine++) { + std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl; + } + } else if (startLine != BLANK_LINE && endLine != BLANK_LINE) { + 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()) || + startLine < 1) { + std::cout << "Line number out of range, this file has " << + static_cast(it->second.second.size()) << " lines" << std::endl; + return; + } + if (endLine > static_cast(it->second.second.size())) { + endLine = static_cast(it->second.second.size()); + } + for (int showLine = startLine - 1; showLine < endLine; showLine++) { + std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl; + } + } +} + +void SourceManager::ListSource(int startLine, int endLine) +{ + const int BLANK_LINE = std::numeric_limits::max(); + const int STATR_LINE_OFFSET = 6; + const int END_LINE_OFFSET = 4; + const int END_LINE = 10; + if (startLine == BLANK_LINE && endLine == BLANK_LINE) { + 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; + } + if (endLine > static_cast(it->second.second.size())) { + endLine = static_cast(it->second.second.size()); + } + for (; showLine <= endLine; showLine++) { + std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl; + } + } else { + ListSourceCodeWithParameters(startLine, endLine); + } +} + +bool SourceManager::IsNumer(const std::string& str) +{ + for (char c : str) { + if (std::isdigit(c)) { + return true; + } + } + return false; +} + +void SourceManager::GetListSource(std::string lineNum) +{ + const int BLANK_LINE = std::numeric_limits::max(); + 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 { + if (!IsNumer(lineNum)) { + return; + } + ListSource(std::atoi(lineNum.c_str()), BLANK_LINE); + } + } else { + ListSource(BLANK_LINE, BLANK_LINE); + } + 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 100644 index 0000000000000000000000000000000000000000..83e2b0e18dd4293977911a8327f12abcfc7f2366 --- /dev/null +++ b/tooling/client/manager/source_manager.h @@ -0,0 +1,57 @@ +/* + * 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 ListSourceCodeWithParameters(int startLine, int endLine); + void ListSource(int startLine, int endLine); + void GetListSource(std::string lineNum); + void GetDebugInfo(const std::unique_ptr json); + bool IsNumer(const std::string& str); + +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/stack_manager.cpp b/tooling/client/manager/stack_manager.cpp index 0dd28a2523039ff37e4213a5afc74a55d58a1ff0..a9940cb5e42dbfad7d19061243b29800a0b3bf0f 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 "tooling/client/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 bca471577ca3d35105f5896982a4658477277c30..99c65e322a9a3bcf953e6d4163da0b55e9c26956 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 08b2cf3b425e4f7ead8d2857e50a32c1c85f8095..38e3b25969904f87c4b4b13d79fe5d530fb85be9 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 0b4eaacce984410de486698e6d5f04e0c0591b7e..7bd72b7efd94cb828e6791c3436f6b96da8a9755 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/manager/watch_manager.cpp b/tooling/client/manager/watch_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffa598525b9493337e156ce805b7dad9470790f3 --- /dev/null +++ b/tooling/client/manager/watch_manager.cpp @@ -0,0 +1,263 @@ +/* + * 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::SendRequestWatch(const int32_t &watchInfoIndex, const std::string &callFrameId) +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + watchInfoMap_.emplace(id, 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::GetPropertiesCommand(const int32_t &watchInfoIndex, const std::string &objectId) +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + watchInfoMap_.emplace(id, watchInfoIndex); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Runtime.getProperties"); + + std::unique_ptr params = PtJson::CreateObject(); + params->Add("accessorPropertiesOnly", false); + params->Add("generatePreview", true); + params->Add("objectId", objectId.c_str()); + params->Add("ownProperties", true); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + return; +} + +void WatchManager::RequestWatchInfo(const std::unique_ptr &json) +{ + Result ret = json->GetString("callFrameId", &callFrameId_); + if (ret != Result::SUCCESS) { + LOGE("arkdb: find callFrameId error"); + return; + } + for (uint i = 0; i < watchInfoList_.size(); i++) { + SendRequestWatch(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; +} + +void WatchManager::SetWatchInfoMap(const int &id, const int &index) +{ + watchInfoMap_.emplace(id, index); +} + +bool WatchManager::HandleWatchResult(const 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) { + ShowWatchResult2(id, std::move(json)); + 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(const std::unique_ptr &result, int32_t id) +{ + std::string type; + Result 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 << " " << watchInfoList_[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; + } + GetPropertiesCommand(it->second, objectId); + 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 << " " << watchInfoList_[it->second] << " = " << description << std::endl; + } + watchInfoMap_.erase(id); + DebugTrueState(); + return true; +} + +void WatchManager::OutputWatchResult(const std::unique_ptr &watchResult) +{ + for (int32_t i = 0; i < watchResult->GetSize(); i++) { + std::string name; + Result 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 << ", "; + } + } + return; +} + +bool WatchManager::ShowWatchResult2(const int &id, const std::unique_ptr &result) +{ + std::unique_ptr resultWatch; + Result 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; + } + auto it = watchInfoMap_.find(id); + if (it == watchInfoMap_.end()) { + return false; + } + std::cout << " " << watchInfoList_[it->second] << " = { "; + OutputWatchResult(std::move(watchResult)); + std::cout << " }" << std::endl; + inputRowFlag_--; + if (inputRowFlag_ == 0) { + std::cout << ">>> "; + fflush(stdout); + isShowWatchInfo_ = true; + } + DebugTrueState(); + watchInfoMap_.erase(id); + 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 100644 index 0000000000000000000000000000000000000000..bf7a2b387c4b5d3f0be01de77ebcd46cac146af2 --- /dev/null +++ b/tooling/client/manager/watch_manager.h @@ -0,0 +1,63 @@ +/* + * 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 SendRequestWatch(const int32_t &watchInfoIndex, const std::string &callFrameId); + void GetPropertiesCommand(const int32_t &watchInfoIndex, const std::string &objectId); + void RequestWatchInfo(const std::unique_ptr &json); + void AddWatchInfo(const std::string& watchInfo); + + bool GetDebugState(); + void DebugFalseState(); + void DebugTrueState(); + bool HandleWatchResult(const std::unique_ptr &json, int32_t id); + bool ShowWatchResult(const std::unique_ptr &result, int32_t id); + void OutputWatchResult(const std::unique_ptr &watchResult); + bool ShowWatchResult2(const int &id, const std::unique_ptr &result); + std::string GetCallFrameId(); + int GetWatchInfoSize(); + void SetWatchInfoMap(const int &id, const int &index); + +private: + [[maybe_unused]] int32_t sessionId_; + std::vector watchInfoList_; + std::unordered_map watchInfoMap_; + bool IsDebug_; + std::string callFrameId_; + 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 new file mode 100755 index 0000000000000000000000000000000000000000..d6569947ea748688aed8d794ba35280acd2db016 --- /dev/null +++ b/tooling/client/session/session.cpp @@ -0,0 +1,208 @@ +/* + * 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/session/session.h" + +#include "common/log_wrapper.h" +#include "tooling/client/manager/message_manager.h" +#include "tooling/base/pt_json.h" +#include "tooling/client/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), sourceManager_(sessionId), watchManager_(sessionId) +{ +} + +void Session::SocketMessageLoop() +{ + while (cliSocket_.IsConnected()) { + std::string decMessage = cliSocket_.Decode(); + uint32_t len = decMessage.length(); + if (len == 0) { + continue; + } + LOGI("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::CreateSocket() +{ + 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; + } + + return 0; +} + +int Session::Start() +{ + if (CreateSocket()) { + return -1; + } + + uv_thread_create(&socketTid_, SocketMessageThread, &sessionId_); + return 0; +} + +int Session::Stop() +{ + 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); + } + } +} + +int SessionManager::CreateTestSession(std::string& sockInfo) +{ + uint32_t sessionId = 0; + sessions_[sessionId] = std::make_unique(sessionId, sockInfo); + if (sessions_[sessionId]->CreateSocket()) { + sessions_[sessionId] = nullptr; + return -1; + } + + return 0; +} +} \ 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 0000000000000000000000000000000000000000..aeaba1ac37e623e77bc68cdef59f55c019cd8aca --- /dev/null +++ b/tooling/client/session/session.h @@ -0,0 +1,180 @@ +/* + * 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 "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 { +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 CreateSocket(); + 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_; + } + + WebsocketClient& GetWebsocketClient() + { + return cliSocket_; + } + + ProfilerSingleton& GetProfilerSingleton() + { + return profiler_; + } + + std::string GetSocketStateString() + { + return cliSocket_.GetSocketStateString(); + } + + void ProcSocketMsg(char* msg) + { + domainManager_.DispatcherReply(msg); + } + + SourceManager& GetSourceManager() + { + return sourceManager_; + } + + WatchManager& GetWatchManager() + { + return watchManager_; + } + +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_; + SourceManager sourceManager_; + WatchManager watchManager_; +}; + +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); + int CreateTestSession(std::string& sockInfo); + +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 abb24ded492ad6e2cbf76dd677e49771b898ef8c..41cd28d6ca8907e69e327c2ac7e5f1f6181e240f 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 "tooling/client/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,29 +251,56 @@ 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"); + bool result = profilerClient.DispatcherCmd(cmd); + return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL; +} + +ErrCode CliCommand::HandleDebuggerCommand(const std::string &cmd) +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + BreakPointManager &breakpoint = session->GetBreakPointManager(); + SourceManager &sourceManager = session->GetSourceManager(); + WatchManager &watchManager = session->GetWatchManager(); + if (cmd == "display") { + breakpoint.Show(); + return ErrCode::ERR_OK; + } + + if (cmd == "infosource") { + if (GetArgList().size() == 1) { + sourceManager.GetFileSource(std::atoi(GetArgList()[0].c_str())); + } else { + sourceManager.GetFileName(); } - } else { - return ErrCode::ERR_FAIL; + return ErrCode::ERR_OK; } - return ErrCode::ERR_OK; + + if (cmd == "list" && watchManager.GetDebugState()) { + 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.SendRequestWatch(watchManager.GetWatchInfoSize() - 1, watchManager.GetCallFrameId()); + } + return ErrCode::ERR_OK; + } + return 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(); - if (cmd == "display") { - breakpoint.Show(); - return ErrCode::ERR_OK; - } + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + DebuggerClient &debuggerCli = session->GetDomainManager().GetDebuggerClient(); + BreakPointManager &breakpoint = session->GetBreakPointManager(); if (cmd == "delete") { std::string bnumber = GetArgList()[0]; @@ -281,12 +319,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(); } @@ -294,58 +332,98 @@ 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; + if (HandleDebuggerCommand(cmd) == ErrCode::ERR_OK) { + return ErrCode::ERR_OK; } - 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::TestCommand(const std::string &cmd) +ErrCode CliCommand::SessionAddCommand([[maybe_unused]] 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"); + VecStr argList = GetArgList(); + if (argList.size() >= 1) { + if (!SessionManager::getInstance().CreateNewSession(argList[0])) { + 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) +{ + if (cmd == "success" || cmd == "fail") { + 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 4ae35d82818dacff48cb1491983b6c586c785203..5410695e356a7a73de5db50fff448a6e1c821220 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 "tooling/client/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 = 1u; i < cliCmdStr.size(); i++) { argList_.push_back(cliCmdStr[i]); @@ -53,17 +54,17 @@ public: ErrCode ExecCommand(); void CreateCommandMap(); ErrCode HeapProfilerCommand(const std::string &cmd); + ErrCode HandleDebuggerCommand(const std::string &cmd); 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 +75,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 725d8ac411eb0ca980d081a1c2b9a83c001b58db..96e9cc95a69ef76e2b562a8d7c4582298b532a95 100644 --- a/tooling/client/utils/utils.cpp +++ b/tooling/client/utils/utils.cpp @@ -17,7 +17,6 @@ #include "common/log_wrapper.h" #include #include -#include namespace OHOS::ArkCompiler::Toolchain { bool Utils::GetCurrentTime(char *date, char *tim, size_t size) @@ -55,6 +54,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 1a17afb45b1d8dcb4146f5e93521f09ef3e6aa06..6d59c24f8db948149026a01cfef5b20130ec904e 100644 --- a/tooling/client/utils/utils.h +++ b/tooling/client/utils/utils.h @@ -24,6 +24,7 @@ class Utils { public: static bool RealPath(const std::string &path, std::string &realPath, bool readOnly = true); 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 15af188778cb0b935bd841a62727ea4ba84c1e6e..9cc9f21d8c839e83705789eaec689212fca5f9d2 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 56772e0329427f5079895966f7a58062d683811b..3fb7f6bb1e47cab44e5eb38d6f03a2dbaafd6673 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}; diff --git a/tooling/test/BUILD.gn b/tooling/test/BUILD.gn index 2fc6294e11b716324a6d6c2871ab03eeba561107..9c2b4655f766024450c868a9fa49aeb591578125 100644 --- a/tooling/test/BUILD.gn +++ b/tooling/test/BUILD.gn @@ -28,6 +28,7 @@ config("debug_api_test") { "//arkcompiler/ets_runtime", "../..", "//third_party/cJSON", + "//third_party/libuv/include", ] } diff --git a/tooling/test/client_utils/test_util.cpp b/tooling/test/client_utils/test_util.cpp index 7fa968360bc1c2d82b21f56743068743464b94f3..db52114a0dec29c2c8e080784415e1cbe17e8746 100644 --- a/tooling/test/client_utils/test_util.cpp +++ b/tooling/test/client_utils/test_util.cpp @@ -18,6 +18,7 @@ #include "tooling/client/domain/debugger_client.h" #include "tooling/client/domain/runtime_client.h" #include "tooling/client/utils/cli_command.h" +#include "tooling/client/session/session.h" namespace panda::ecmascript::tooling::test { TestMap TestUtil::testMap_; @@ -67,19 +68,19 @@ std::ostream &operator<<(std::ostream &out, ActionRule value) return out << s; } -void TestUtil::NotifySuccess(int cmdId, DomainManager &domainManager, WebsocketClient &client) +void TestUtil::NotifySuccess() { std::vector cliCmdStr = { "success" }; - CliCommand cmd(cliCmdStr, cmdId, domainManager, client); + CliCommand cmd(cliCmdStr, 0); if (cmd.ExecCommand() == ErrCode::ERR_FAIL) { LOG_DEBUGGER(ERROR) << "ExecCommand Test.success fail"; } } -void TestUtil::NotifyFail(int cmdId, DomainManager &domainManager, WebsocketClient &client) +void TestUtil::NotifyFail() { std::vector cliCmdStr = { "fail" }; - CliCommand cmd(cliCmdStr, cmdId, domainManager, client); + CliCommand cmd(cliCmdStr, 0); if (cmd.ExecCommand() == ErrCode::ERR_FAIL) { LOG_DEBUGGER(ERROR) << "ExecCommand Test.fail fail"; } @@ -87,7 +88,6 @@ void TestUtil::NotifyFail(int cmdId, DomainManager &domainManager, WebsocketClie void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &name) { - int cmdId = 0; #ifdef OHOS_PLATFORM auto correntPid = getpid(); #endif @@ -98,28 +98,23 @@ void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &na } else if (pid == 0) { LOG_DEBUGGER(INFO) << "fork son pid: " << getpid(); std::this_thread::sleep_for(std::chrono::microseconds(500000)); // 500000: 500ms for wait debugger - DomainManager domainManager; - WebsocketClient client; #ifdef OHOS_PLATFORM std::string pidStr = std::to_string(correntPid); - std::string sockName = pidStr + "PandaDebugger"; - bool ret = client.InitToolchainWebSocketForSockName(sockName, 120); + std::string sockInfo = pidStr + "PandaDebugger"; #else - bool ret = client.InitToolchainWebSocketForPort(port, 120); + std::string sockInfo = std::to_string(port); #endif - LOG_ECMA_IF(!ret, FATAL) << "InitToolchainWebSocketForPort fail"; - ret = client.ClientSendWSUpgradeReq(); - LOG_ECMA_IF(!ret, FATAL) << "ClientSendWSUpgradeReq fail"; - ret = client.ClientRecvWSUpgradeRsp(); - LOG_ECMA_IF(!ret, FATAL) << "ClientRecvWSUpgradeRsp fail"; + int ret = SessionManager::getInstance().CreateTestSession(sockInfo); + LOG_ECMA_IF(ret, FATAL) << "CreateTestSession fail"; + WebsocketClient &client = SessionManager::getInstance().GetCurrentSession()->GetWebsocketClient(); auto &testAction = TestUtil::GetTest(name)->testAction; for (const auto &action: testAction) { LOG_DEBUGGER(INFO) << "message: " << action.message; bool success = true; if (action.action == SocketAction::SEND) { std::vector cliCmdStr = Utils::SplitString(action.message, " "); - CliCommand cmd(cliCmdStr, cmdId++, domainManager, client); + CliCommand cmd(cliCmdStr, 0); success = (cmd.ExecCommand() == ErrCode::ERR_OK); } else { ASSERT(action.action == SocketAction::RECV); @@ -143,14 +138,14 @@ void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &na } if (!success) { LOG_DEBUGGER(ERROR) << "Notify fail"; - NotifyFail(cmdId++, domainManager, client); - client.Close(); + NotifyFail(); + SessionManager::getInstance().DelSessionById(0); exit(-1); } } - NotifySuccess(cmdId++, domainManager, client); - client.Close(); + NotifySuccess(); + SessionManager::getInstance().DelSessionById(0); exit(0); } LOG_DEBUGGER(INFO) << "ForkSocketClient end"; diff --git a/tooling/test/client_utils/test_util.h b/tooling/test/client_utils/test_util.h index c7cb883ba95fcfb364b8315acd5b86e7a8b33636..f7839ccedd23db69ef25d985e50d156100c3435a 100644 --- a/tooling/test/client_utils/test_util.h +++ b/tooling/test/client_utils/test_util.h @@ -63,8 +63,8 @@ public: static void ForkSocketClient(int port, const std::string &name); private: - static void NotifyFail(int cmdId, DomainManager &domainManager, WebsocketClient &client); - static void NotifySuccess(int cmdId, DomainManager &domainManager, WebsocketClient &client); + static void NotifyFail(); + static void NotifySuccess(); static TestMap testMap_; }; diff --git a/tooling/test/testcases/js_breakpoint_test.h b/tooling/test/testcases/js_breakpoint_test.h index b76c7ea3628451af14747c98e27094c7d60b3ee1..09d968af940386ca1688cbdf3e7215a3c681d0cd 100644 --- a/tooling/test/testcases/js_breakpoint_test.h +++ b/tooling/test/testcases/js_breakpoint_test.h @@ -35,7 +35,7 @@ public: // break on start {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, // set breakpoint - {SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 21"}, + {SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 22"}, {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, // hit breakpoint after resume first time {SocketAction::SEND, "resume"},