1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "tooling/dynamic/client/utils/cli_command.h"
17 #include "tooling/dynamic/client/tcpServer/tcp_server.h"
18 #include "manager/message_manager.h"
19
20 namespace OHOS::ArkCompiler::Toolchain {
21 uv_loop_t* g_loop;
22
ReleaseHandle(uv_async_t * releaseHandle)23 void ReleaseHandle([[maybe_unused]] uv_async_t *releaseHandle)
24 {
25 uv_close(reinterpret_cast<uv_handle_t*>(g_inputSignal), [](uv_handle_t* handle) {
26 if (handle != nullptr) {
27 uv_async_t* asyncHandle = reinterpret_cast<uv_async_t*>(handle);
28 if (asyncHandle->data != nullptr) {
29 free(asyncHandle->data);
30 asyncHandle->data = nullptr;
31 }
32 delete asyncHandle;
33 asyncHandle = nullptr;
34 g_inputSignal = nullptr;
35 }
36 });
37
38 uv_close(reinterpret_cast<uv_handle_t*>(g_socketSignal), [](uv_handle_t* handle) {
39 if (handle != nullptr) {
40 delete reinterpret_cast<uv_async_t*>(handle);
41 handle = nullptr;
42 g_socketSignal = nullptr;
43 }
44 });
45
46 uv_close(reinterpret_cast<uv_handle_t*>(g_releaseHandle), [](uv_handle_t* handle) {
47 if (handle != nullptr) {
48 delete reinterpret_cast<uv_async_t*>(handle);
49 handle = nullptr;
50 g_releaseHandle = nullptr;
51 }
52 });
53
54 if (g_loop != nullptr) {
55 uv_stop(g_loop);
56 }
57 }
58
InputMessageInSession(uint32_t sessionId,std::vector<std::string> & cliCmdStr)59 void InputMessageInSession(uint32_t sessionId, std::vector<std::string>& cliCmdStr)
60 {
61 CliCommand cmd(cliCmdStr, sessionId);
62 cmd.ExecCommand();
63 return;
64 }
65
InputOnMessage(uv_async_t * handle)66 void InputOnMessage(uv_async_t *handle)
67 {
68 char* msg = static_cast<char*>(handle->data);
69 std::string inputStr = std::string(msg);
70 if (msg != nullptr) {
71 free(msg);
72 }
73 std::vector<std::string> cliCmdStr = Utils::SplitString(inputStr, " ");
74 if (cliCmdStr[0] == "forall") {
75 if (strstr(cliCmdStr[1].c_str(), "session") != nullptr) {
76 std::cout << "command " << cliCmdStr[1] << " not support forall" << std::endl;
77 } else {
78 cliCmdStr.erase(cliCmdStr.begin());
79 SessionManager::getInstance().CmdForAllSessions(std::bind(InputMessageInSession, std::placeholders::_1,
80 cliCmdStr));
81 }
82 } else {
83 uint32_t sessionId = SessionManager::getInstance().GetCurrentSessionId();
84 InputMessageInSession(sessionId, cliCmdStr);
85 }
86
87 if (TcpServer::getInstance().IsServerActive()) {
88 TcpServer::getInstance().TcpServerWrite("InputOnMessage");
89 } else {
90 std::cout << ">>> ";
91 fflush(stdout);
92 }
93 }
94
GetInputCommand(void * arg)95 void GetInputCommand([[maybe_unused]] void *arg)
96 {
97 std::cout << ">>> ";
98 std::string inputStr;
99 while (getline(std::cin, inputStr)) {
100 inputStr.erase(0, inputStr.find_first_not_of(" "));
101 if (inputStr.empty()) {
102 std::cout << ">>> ";
103 continue;
104 }
105 if ((!strcmp(inputStr.c_str(), "quit")) || (!strcmp(inputStr.c_str(), "q"))) {
106 LOGE("arkdb: quit");
107 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
108 uv_async_send(g_releaseHandle);
109 }
110 break;
111 }
112 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_inputSignal))) {
113 uint32_t len = inputStr.length();
114 char* msg = (char*)malloc(len + 1);
115 if (msg == nullptr) {
116 continue;
117 }
118 if (strncpy_s(msg, len + 1, inputStr.c_str(), len) != 0) {
119 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
120 uv_async_send(g_releaseHandle);
121 }
122 free(msg);
123 break;
124 }
125 g_inputSignal->data = std::move(msg);
126 uv_async_send(g_inputSignal);
127 }
128 }
129 }
130
SocketOnMessage(uv_async_t * handle)131 void SocketOnMessage([[maybe_unused]] uv_async_t *handle)
132 {
133 uint32_t sessionId = 0;
134 std::string message;
135 while (MessageManager::getInstance().MessagePop(sessionId, message)) {
136 Session *session = SessionManager::getInstance().GetSessionById(sessionId);
137 if (session == nullptr) {
138 LOGE("arkdb get session by id %{public}u failed", sessionId);
139 continue;
140 }
141
142 session->ProcSocketMsg(const_cast<char *>(message.c_str()));
143 }
144
145 if (TcpServer::getInstance().IsServerActive()) {
146 TcpServer::getInstance().TcpServerWrite("SocketOnMessage");
147 }
148 }
149
Main(const int argc,const char ** argv)150 int Main(const int argc, const char** argv)
151 {
152 if (argc < 2) { // 2: two parameters
153 LOGE("arkdb is missing a parameter");
154 return -1;
155 }
156 if (strstr(argv[0], "arkdb") != nullptr) {
157 std::string sockInfo(argv[1]);
158 if (SessionManager::getInstance().CreateDefaultSession(sockInfo)) {
159 LOGE("arkdb create default session failed");
160 return -1;
161 }
162
163 g_loop = uv_default_loop();
164
165 g_inputSignal = new uv_async_t;
166 uv_async_init(g_loop, g_inputSignal, reinterpret_cast<uv_async_cb>(InputOnMessage));
167
168 g_socketSignal = new uv_async_t;
169 uv_async_init(g_loop, g_socketSignal, reinterpret_cast<uv_async_cb>(SocketOnMessage));
170
171 g_releaseHandle = new uv_async_t;
172 uv_async_init(g_loop, g_releaseHandle, reinterpret_cast<uv_async_cb>(ReleaseHandle));
173
174 if (argc > 2 && strcmp(argv[2], "server") == 0) { // 2: two parameters
175 if (TcpServer::getInstance().CreateTcpServer(argv)) {
176 LOGE("arkdb create TcpServer failed");
177 return -1;
178 }
179 } else {
180 uv_thread_t inputTid;
181 uv_thread_create(&inputTid, GetInputCommand, nullptr);
182 }
183
184 uv_run(g_loop, UV_RUN_DEFAULT);
185 }
186 return 0;
187 }
188 } // OHOS::ArkCompiler::Toolchain
189
main(int argc,const char ** argv)190 int main(int argc, const char **argv)
191 {
192 return OHOS::ArkCompiler::Toolchain::Main(argc, argv);
193 }
194