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 <cstring>
17 #include <iostream>
18 #include <vector>
19 #include <pthread.h>
20 #include <thread>
21 #include <uv.h>
22 #include <securec.h>
23
24 #include "tooling/client/utils/cli_command.h"
25 #include "tooling/client/session/session.h"
26 #include "tooling/client/tcpServer/tcp_server.h"
27 #include "manager/message_manager.h"
28
29 namespace OHOS::ArkCompiler::Toolchain {
30 uv_loop_t* g_loop;
31
ReleaseHandle(uv_async_t * releaseHandle)32 void ReleaseHandle([[maybe_unused]] uv_async_t *releaseHandle)
33 {
34 uv_close(reinterpret_cast<uv_handle_t*>(g_inputSignal), [](uv_handle_t* handle) {
35 if (handle != nullptr) {
36 uv_async_t* asyncHandle = reinterpret_cast<uv_async_t*>(handle);
37 if (asyncHandle->data != nullptr) {
38 free(asyncHandle->data);
39 asyncHandle->data = nullptr;
40 }
41 delete asyncHandle;
42 asyncHandle = nullptr;
43 g_inputSignal = nullptr;
44 }
45 });
46
47 uv_close(reinterpret_cast<uv_handle_t*>(g_socketSignal), [](uv_handle_t* handle) {
48 if (handle != nullptr) {
49 delete reinterpret_cast<uv_async_t*>(handle);
50 handle = nullptr;
51 g_socketSignal = nullptr;
52 }
53 });
54
55 uv_close(reinterpret_cast<uv_handle_t*>(g_releaseHandle), [](uv_handle_t* handle) {
56 if (handle != nullptr) {
57 delete reinterpret_cast<uv_async_t*>(handle);
58 handle = nullptr;
59 g_releaseHandle = nullptr;
60 }
61 });
62
63 if (g_loop != nullptr) {
64 uv_stop(g_loop);
65 }
66 }
67
InputMessageInSession(uint32_t sessionId,std::vector<std::string> & cliCmdStr)68 void InputMessageInSession(uint32_t sessionId, std::vector<std::string>& cliCmdStr)
69 {
70 CliCommand cmd(cliCmdStr, sessionId);
71 cmd.ExecCommand();
72 return;
73 }
74
InputOnMessage(uv_async_t * handle)75 void InputOnMessage(uv_async_t *handle)
76 {
77 char* msg = static_cast<char*>(handle->data);
78 std::string inputStr = std::string(msg);
79 if (msg != nullptr) {
80 free(msg);
81 }
82 std::vector<std::string> cliCmdStr = Utils::SplitString(inputStr, " ");
83 if (cliCmdStr[0] == "forall") {
84 if (strstr(cliCmdStr[1].c_str(), "session") != nullptr) {
85 std::cout << "command " << cliCmdStr[1] << " not support forall" << std::endl;
86 } else {
87 cliCmdStr.erase(cliCmdStr.begin());
88 SessionManager::getInstance().CmdForAllSessions(std::bind(InputMessageInSession, std::placeholders::_1,
89 cliCmdStr));
90 }
91 } else {
92 uint32_t sessionId = SessionManager::getInstance().GetCurrentSessionId();
93 InputMessageInSession(sessionId, cliCmdStr);
94 }
95
96 if (TcpServer::getInstance().IsServerActive()) {
97 TcpServer::getInstance().TcpServerWrite("InputOnMessage");
98 } else {
99 std::cout << ">>> ";
100 fflush(stdout);
101 }
102 }
103
GetInputCommand(void * arg)104 void GetInputCommand([[maybe_unused]] void *arg)
105 {
106 std::cout << ">>> ";
107 std::string inputStr;
108 while (getline(std::cin, inputStr)) {
109 inputStr.erase(0, inputStr.find_first_not_of(" "));
110 if (inputStr.empty()) {
111 std::cout << ">>> ";
112 continue;
113 }
114 if ((!strcmp(inputStr.c_str(), "quit")) || (!strcmp(inputStr.c_str(), "q"))) {
115 LOGE("arkdb: quit");
116 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
117 uv_async_send(g_releaseHandle);
118 }
119 break;
120 }
121 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_inputSignal))) {
122 uint32_t len = inputStr.length();
123 char* msg = (char*)malloc(len + 1);
124 if (msg == nullptr) {
125 continue;
126 }
127 if (strncpy_s(msg, len + 1, inputStr.c_str(), len) != 0) {
128 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
129 uv_async_send(g_releaseHandle);
130 }
131 free(msg);
132 break;
133 }
134 g_inputSignal->data = std::move(msg);
135 uv_async_send(g_inputSignal);
136 }
137 }
138 }
139
SocketOnMessage(uv_async_t * handle)140 void SocketOnMessage([[maybe_unused]] uv_async_t *handle)
141 {
142 uint32_t sessionId = 0;
143 std::string message;
144 while (MessageManager::getInstance().MessagePop(sessionId, message)) {
145 Session *session = SessionManager::getInstance().GetSessionById(sessionId);
146 if (session == nullptr) {
147 LOGE("arkdb get session by id %{public}u failed", sessionId);
148 continue;
149 }
150
151 session->ProcSocketMsg(const_cast<char *>(message.c_str()));
152 }
153
154 if (TcpServer::getInstance().IsServerActive()) {
155 TcpServer::getInstance().TcpServerWrite("SocketOnMessage");
156 }
157 }
158
Main(const int argc,const char ** argv)159 int Main(const int argc, const char** argv)
160 {
161 if (argc < 2) { // 2: two parameters
162 LOGE("arkdb is missing a parameter");
163 return -1;
164 }
165 if (strstr(argv[0], "arkdb") != nullptr) {
166 std::string sockInfo(argv[1]);
167 if (SessionManager::getInstance().CreateDefaultSession(sockInfo)) {
168 LOGE("arkdb create default session failed");
169 return -1;
170 }
171
172 g_loop = uv_default_loop();
173
174 g_inputSignal = new uv_async_t;
175 uv_async_init(g_loop, g_inputSignal, reinterpret_cast<uv_async_cb>(InputOnMessage));
176
177 g_socketSignal = new uv_async_t;
178 uv_async_init(g_loop, g_socketSignal, reinterpret_cast<uv_async_cb>(SocketOnMessage));
179
180 g_releaseHandle = new uv_async_t;
181 uv_async_init(g_loop, g_releaseHandle, reinterpret_cast<uv_async_cb>(ReleaseHandle));
182
183 if (argc > 2 && strcmp(argv[2], "server") == 0) { // 2: two parameters
184 if (TcpServer::getInstance().CreateTcpServer(argv)) {
185 LOGE("arkdb create TcpServer failed");
186 return -1;
187 }
188 } else {
189 uv_thread_t inputTid;
190 uv_thread_create(&inputTid, GetInputCommand, nullptr);
191 }
192
193 uv_run(g_loop, UV_RUN_DEFAULT);
194 }
195 return 0;
196 }
197 } // OHOS::ArkCompiler::Toolchain
198
main(int argc,const char ** argv)199 int main(int argc, const char **argv)
200 {
201 return OHOS::ArkCompiler::Toolchain::Main(argc, argv);
202 }
203