2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/network/common/network-performance-client.h>
27 #include <dali/internal/network/common/automation.h>
28 #include <dali/internal/network/common/network-performance-protocol.h>
29 #include <dali/internal/network/common/socket-interface.h>
39 const float MICROSECONDS_TO_SECOND = 1e-6;
40 const char UNKNOWN_CMD[] = "Command or parameter invalid, type help for list of commands\n";
43 * helper class to store data along with the automation callback.
45 class AutomationCallback : public CallbackBase
49 * instead of using templates, or having different callback classes for each callback
50 * we use a command id that decides which static function to call on the Automation class.
60 AutomationCallback(unsigned int clientId, ClientSendDataInterface& sendDataInterface)
61 : CallbackBase(reinterpret_cast<void*>(this),
62 NULL, // we get the dispatcher to call function directly
63 reinterpret_cast<CallbackBase::Dispatcher>(&AutomationCallback::Dispatcher)),
64 mSendDataInterface(sendDataInterface),
65 mCommandId(UNKNOWN_COMMAND),
70 void AssignSetPropertyCommand(std::string setPropertyCommand)
72 mCommandId = SET_PROPERTY;
73 mCommandString = setPropertyCommand;
76 void AssignDumpSceneCommand()
78 mCommandId = DUMP_SCENE;
81 void AssignCustomCommand(std::string&& customCommand)
83 mCommandId = CUSTOM_COMMAND;
84 mCommandString = std::move(customCommand);
93 Automation::SetProperty(mCommandString);
98 Automation::DumpScene(mClientId, &mSendDataInterface);
103 Automation::SetCustomCommand(mCommandString);
108 DALI_ASSERT_DEBUG(0 && "Unknown command");
113 static void Dispatcher(CallbackBase& base)
115 AutomationCallback& automationCallback(static_cast<AutomationCallback&>(base));
116 automationCallback.RunCallback();
120 std::string mCommandString; ///< command string for property or custom command
121 ClientSendDataInterface& mSendDataInterface; ///< Abstract client send data interface
122 CommandId mCommandId; ///< command id
123 const unsigned int mClientId; ///< client id
127 * @brief Helper to ensure the AutomationCallback method we want is called in the main thread
130 void TriggerOnMainThread(unsigned int clientId, ClientSendDataInterface& sendDataInterface, T&& lambda)
132 // this needs to be run on the main thread, use the trigger event....
133 AutomationCallback* callback = new AutomationCallback(clientId, sendDataInterface);
135 sendDataInterface.TriggerMainThreadAutomation(callback);
138 } // unnamed namespace
140 NetworkPerformanceClient::NetworkPerformanceClient(pthread_t* thread,
141 SocketInterface* socket,
142 unsigned int clientId,
143 ClientSendDataInterface& sendDataInterface,
144 SocketFactoryInterface& socketFactory)
147 mMarkerBitmask(PerformanceMarker::FILTERING_DISABLED),
148 mSendDataInterface(sendDataInterface),
149 mSocketFactoryInterface(socketFactory),
151 mConsoleClient(false)
155 NetworkPerformanceClient::~NetworkPerformanceClient()
157 if(mSocket->SocketIsOpen())
159 mSocket->CloseSocket();
161 mSocketFactoryInterface.DestroySocket(mSocket);
164 unsigned int NetworkPerformanceClient::GetId() const
169 SocketInterface& NetworkPerformanceClient::GetSocket()
174 bool NetworkPerformanceClient::WriteSocket(const void* buffer, unsigned int bufferSizeInBytes)
176 return mSocket->Write(buffer, bufferSizeInBytes);
179 bool NetworkPerformanceClient::TransmitMarker(const PerformanceMarker& marker, const char* const description)
181 if(!marker.IsFilterEnabled(mMarkerBitmask))
187 // write out the time stamp
189 double usec = marker.GetTimeStamp().microseconds;
190 int size = asprintf(&buffer, "%.6f (seconds), %s\n", usec * MICROSECONDS_TO_SECOND, description);
191 auto retVal = mSocket->Write(buffer, size);
196 // todo serialize the data
200 void NetworkPerformanceClient::ExitSelect()
202 mSocket->ExitSelect();
205 pthread_t* NetworkPerformanceClient::GetThread()
210 void NetworkPerformanceClient::ProcessCommand(char* buffer, unsigned int bufferSizeInBytes)
212 // if connected via console, then strip off the carriage return, and switch to console mode
213 if(buffer[bufferSizeInBytes - 1] == '\n')
215 buffer[bufferSizeInBytes - 1] = 0;
216 mConsoleClient = true;
218 unsigned int param(0);
219 std::string stringParam;
220 PerformanceProtocol::CommandId commandId(PerformanceProtocol::UNKNOWN_COMMAND);
222 bool ok = PerformanceProtocol::GetCommandId(buffer, bufferSizeInBytes, commandId, param, stringParam);
225 WriteSocket(UNKNOWN_CMD, sizeof(UNKNOWN_CMD));
228 std::string response;
232 case PerformanceProtocol::HELP_MESSAGE:
234 response = PerformanceProtocol::GetHelpMessage();
238 case PerformanceProtocol::ENABLE_TIME_MARKER_BIT_MASK:
240 mMarkerBitmask = static_cast<PerformanceMarker::MarkerFilter>(param);
241 response = "enable time marker ";
245 case PerformanceProtocol::DUMP_SCENE_GRAPH:
247 TriggerOnMainThread(mClientId, mSendDataInterface, [&](AutomationCallback* callback) { callback->AssignDumpSceneCommand(); });
251 case PerformanceProtocol::SET_PROPERTIES:
253 TriggerOnMainThread(mClientId, mSendDataInterface, [&](AutomationCallback* callback) { callback->AssignSetPropertyCommand(stringParam); });
254 response = "Completed";
258 case PerformanceProtocol::CUSTOM_COMMAND:
260 TriggerOnMainThread(mClientId, mSendDataInterface, [&](AutomationCallback* callback) { callback->AssignCustomCommand(std::move(stringParam)); });
261 response = "Completed";
265 case PerformanceProtocol::LIST_METRICS_AVAILABLE:
266 case PerformanceProtocol::ENABLE_METRIC:
267 case PerformanceProtocol::DISABLE_METRIC:
269 response = "Metrics currently not supported";
274 response = UNKNOWN_CMD;
278 if(!response.empty())
280 // add a carriage return for console clients
285 WriteSocket(response.c_str(), response.length());
289 } // namespace Adaptor
291 } // namespace Internal