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