Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "SessionServerAppManager.h"
21 : #include "RialtoServerManagerLogging.h"
22 : #include "Utils.h"
23 : #include <algorithm>
24 : #include <future>
25 : #include <utility>
26 :
27 : namespace rialto::servermanager::common
28 : {
29 45 : SessionServerAppManager::SessionServerAppManager(
30 : std::unique_ptr<ipc::IController> &ipcController, const std::shared_ptr<service::IStateObserver> &stateObserver,
31 : std::unique_ptr<ISessionServerAppFactory> &&sessionServerAppFactory,
32 : std::unique_ptr<IHealthcheckServiceFactory> &&healthcheckServiceFactory,
33 : const std::shared_ptr<firebolt::rialto::common::IEventThreadFactory> &eventThreadFactory,
34 45 : const firebolt::rialto::ipc::INamedSocketFactory &namedSocketFactory)
35 45 : : m_ipcController{ipcController},
36 90 : m_eventThread{eventThreadFactory->createEventThread("rialtoservermanager-appmanager")},
37 45 : m_sessionServerAppFactory{std::move(sessionServerAppFactory)}, m_stateObserver{stateObserver},
38 45 : m_healthcheckService{healthcheckServiceFactory->createHealthcheckService(*this)},
39 135 : m_namedSocketFactory{namedSocketFactory}, m_isShuttingDown{false}
40 : {
41 45 : }
42 :
43 90 : SessionServerAppManager::~SessionServerAppManager()
44 : {
45 45 : m_eventThread->add(&SessionServerAppManager::shutdownAllSessionServers, this);
46 45 : m_eventThread->flush();
47 45 : m_eventThread.reset();
48 90 : }
49 :
50 48 : void SessionServerAppManager::setShuttingDown()
51 : {
52 48 : m_isShuttingDown = true;
53 : }
54 :
55 8 : void SessionServerAppManager::preloadSessionServers(unsigned numOfPreloadedServers)
56 : {
57 8 : m_eventThread->add(
58 8 : [this, numOfPreloadedServers]()
59 : {
60 16 : for (unsigned i = 0; i < numOfPreloadedServers; ++i)
61 : {
62 8 : connectSessionServer(preloadSessionServer());
63 : }
64 8 : });
65 : }
66 :
67 38 : bool SessionServerAppManager::initiateApplication(const std::string &appName,
68 : const firebolt::rialto::common::SessionServerState &state,
69 : const firebolt::rialto::common::AppConfig &appConfig)
70 : {
71 38 : std::promise<bool> p;
72 38 : std::future<bool> f{p.get_future()};
73 76 : m_eventThread->add([&]() { return p.set_value(handleInitiateApplication(appName, state, appConfig)); });
74 76 : return f.get();
75 38 : }
76 :
77 38 : bool SessionServerAppManager::handleInitiateApplication(const std::string &appName,
78 : const firebolt::rialto::common::SessionServerState &state,
79 : const firebolt::rialto::common::AppConfig &appConfig)
80 : {
81 38 : RIALTO_SERVER_MANAGER_LOG_INFO("RialtoServerManager requests to launch %s with initial state: %s", appName.c_str(),
82 : toString(state));
83 113 : if (state != firebolt::rialto::common::SessionServerState::NOT_RUNNING &&
84 38 : state != firebolt::rialto::common::SessionServerState::SUSPENDED && !getServerByAppName(appName))
85 : {
86 36 : auto preloadedServer{getPreloadedServer()};
87 36 : if (preloadedServer)
88 : {
89 5 : return configurePreloadedSessionServer(preloadedServer, appName, state, appConfig,
90 10 : m_namedSocketFactory.createNamedSocket());
91 : }
92 31 : return connectSessionServer(launchSessionServer(appName, state, appConfig));
93 36 : }
94 2 : else if (state == firebolt::rialto::common::SessionServerState::NOT_RUNNING ||
95 1 : state == firebolt::rialto::common::SessionServerState::SUSPENDED)
96 : {
97 1 : RIALTO_SERVER_MANAGER_LOG_ERROR("Initialization of %s failed - wrong state", appName.c_str());
98 : }
99 : else
100 : {
101 1 : RIALTO_SERVER_MANAGER_LOG_ERROR("Initialization of %s failed. App is already launched", appName.c_str());
102 : }
103 2 : return false;
104 : }
105 :
106 14 : bool SessionServerAppManager::setSessionServerState(const std::string &appName,
107 : const firebolt::rialto::common::SessionServerState &newState)
108 : {
109 14 : std::promise<bool> p;
110 14 : std::future<bool> f{p.get_future()};
111 28 : m_eventThread->add([&]() { return p.set_value(changeSessionServerState(appName, newState)); });
112 28 : return f.get();
113 14 : }
114 :
115 30 : void SessionServerAppManager::onSessionServerStateChanged(int serverId,
116 : const firebolt::rialto::common::SessionServerState &newState)
117 : {
118 30 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Queue state change of serverId: %d to %s", serverId, toString(newState));
119 : // Event loop needed here, as function caller may be deleted as a result of this call
120 30 : m_eventThread->add(&SessionServerAppManager::handleSessionServerStateChange, this, serverId, newState);
121 : }
122 :
123 3 : void SessionServerAppManager::sendPingEvents(int pingId)
124 : {
125 3 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Queue ping procedure with id: %d", pingId);
126 3 : m_eventThread->add(
127 3 : [this, pingId]()
128 : {
129 3 : if (m_healthcheckService)
130 : {
131 6 : for (const auto &sessionServer : m_sessionServerApps)
132 : {
133 3 : const auto kSessionServerState{sessionServer->getExpectedState()};
134 3 : if (firebolt::rialto::common::SessionServerState::SUSPENDED == kSessionServerState ||
135 2 : firebolt::rialto::common::SessionServerState::NOT_RUNNING == kSessionServerState)
136 : {
137 1 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Ping with id: %d skipped for server: %d as it is in state: %s",
138 : pingId, sessionServer->getServerId(),
139 : toString(kSessionServerState));
140 2 : continue;
141 : }
142 2 : auto serverId{sessionServer->getServerId()};
143 2 : if (!m_ipcController->performPing(serverId, pingId))
144 : {
145 1 : RIALTO_SERVER_MANAGER_LOG_ERROR("Ping with id: %d failed for server: %d", pingId, serverId);
146 1 : m_healthcheckService->onPingFailed(serverId, pingId);
147 1 : continue;
148 : }
149 1 : m_healthcheckService->onPingSent(serverId, pingId);
150 : }
151 : }
152 3 : });
153 : }
154 :
155 2 : void SessionServerAppManager::onAck(int serverId, int pingId, bool success)
156 : {
157 2 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Queue ack handling for serverId: %d ping id: %d", serverId, pingId);
158 2 : m_eventThread->add(&SessionServerAppManager::handleAck, this, serverId, pingId, success);
159 : }
160 :
161 7 : std::string SessionServerAppManager::getAppConnectionInfo(const std::string &appName) const
162 : {
163 7 : std::promise<std::string> p;
164 7 : std::future<std::string> f{p.get_future()};
165 7 : m_eventThread->add(
166 7 : [&]()
167 : {
168 7 : auto sessionServer{getServerByAppName(appName)};
169 7 : if (sessionServer)
170 : {
171 1 : return p.set_value(sessionServer->getSessionManagementSocketName());
172 : }
173 6 : RIALTO_SERVER_MANAGER_LOG_ERROR("App: %s could not be found", appName.c_str());
174 18 : return p.set_value("");
175 7 : });
176 14 : return f.get();
177 7 : }
178 :
179 2 : bool SessionServerAppManager::setLogLevels(const service::LoggingLevels &logLevels) const
180 : {
181 2 : std::promise<bool> p;
182 2 : std::future<bool> f{p.get_future()};
183 2 : m_eventThread->add(
184 2 : [&]()
185 : {
186 2 : setLocalLogLevels(logLevels);
187 2 : if (!m_ipcController->setLogLevels(logLevels))
188 : {
189 1 : RIALTO_SERVER_MANAGER_LOG_WARN("Change log levels failed.");
190 1 : return p.set_value(false);
191 : }
192 1 : RIALTO_SERVER_MANAGER_LOG_INFO("Change log levels succeeded.");
193 1 : return p.set_value(true);
194 : });
195 4 : return f.get();
196 2 : }
197 :
198 4 : void SessionServerAppManager::restartServer(int serverId)
199 : {
200 4 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Queue restart server handling for serverId: %d", serverId);
201 4 : m_eventThread->add(&SessionServerAppManager::handleRestartServer, this, serverId);
202 : }
203 :
204 4 : void SessionServerAppManager::handleRestartServer(int serverId)
205 : {
206 4 : if (m_isShuttingDown)
207 : {
208 1 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Not restarting serverId: %d as server manager is shutting down", serverId);
209 3 : return;
210 : }
211 3 : auto sessionServer{getServerById(serverId)};
212 3 : if (!sessionServer)
213 : {
214 0 : RIALTO_SERVER_MANAGER_LOG_WARN("Unable to restart server, serverId: %d", serverId);
215 0 : return;
216 : }
217 3 : if (m_healthcheckService)
218 : {
219 3 : m_healthcheckService->onServerRemoved(sessionServer->getServerId());
220 : }
221 : // First, get all needed information from current app
222 3 : const std::string kAppName{sessionServer->getAppName()};
223 3 : const firebolt::rialto::common::SessionServerState kState{sessionServer->getExpectedState()};
224 3 : const firebolt::rialto::common::AppConfig kAppConfig{sessionServer->getSessionManagementSocketName(),
225 3 : sessionServer->getClientDisplayName()};
226 3 : std::unique_ptr<firebolt::rialto::ipc::INamedSocket> namedSocket{std::move(sessionServer->releaseNamedSocket())};
227 3 : if (firebolt::rialto::common::SessionServerState::INACTIVE != kState &&
228 2 : firebolt::rialto::common::SessionServerState::ACTIVE != kState)
229 : {
230 2 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Restart server to %s not needed for serverId: %d", toString(kState), serverId);
231 2 : return;
232 : }
233 1 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Restarting server with id: %d", serverId);
234 : // Then kill the app
235 1 : sessionServer->kill();
236 1 : handleSessionServerStateChange(serverId, firebolt::rialto::common::SessionServerState::NOT_RUNNING);
237 1 : sessionServer.reset();
238 :
239 : // Finally, spawn the new app with old settings and set named socket if present
240 1 : auto app = m_sessionServerAppFactory->create(kAppName, kState, kAppConfig, *this, std::move(namedSocket));
241 1 : if (app->launch())
242 : {
243 1 : auto result = m_sessionServerApps.emplace(std::move(app));
244 1 : if (result.second)
245 : {
246 1 : connectSessionServer(*result.first);
247 : }
248 : }
249 : else
250 : {
251 0 : RIALTO_SERVER_MANAGER_LOG_ERROR("Failed to restart server");
252 : }
253 9 : }
254 :
255 3 : bool SessionServerAppManager::resurrectSuspendedServer(const std::shared_ptr<ISessionServerApp> &kSessionServer,
256 : const firebolt::rialto::common::SessionServerState &state)
257 : {
258 3 : const std::string kAppName{kSessionServer->getAppName()};
259 3 : const firebolt::rialto::common::AppConfig kAppConfig{kSessionServer->getSessionManagementSocketName(),
260 3 : kSessionServer->getClientDisplayName()};
261 3 : std::unique_ptr<firebolt::rialto::ipc::INamedSocket> namedSocket{std::move(kSessionServer->releaseNamedSocket())};
262 3 : m_sessionServerApps.erase(kSessionServer);
263 :
264 3 : RIALTO_SERVER_MANAGER_LOG_INFO("Resurrecting server for app: %s", kAppName.c_str());
265 3 : auto app{getPreloadedServer()};
266 3 : if (app)
267 : {
268 1 : configurePreloadedSessionServer(app, kAppName, state, kAppConfig, std::move(namedSocket));
269 1 : m_sessionServerApps.emplace(std::move(app));
270 1 : return true;
271 : }
272 2 : app = m_sessionServerAppFactory->create(kAppName, state, kAppConfig, *this, std::move(namedSocket));
273 2 : if (app->launch())
274 : {
275 1 : auto result = m_sessionServerApps.emplace(std::move(app));
276 1 : if (result.second)
277 : {
278 1 : return connectSessionServer(*result.first);
279 : }
280 : }
281 : else
282 : {
283 1 : RIALTO_SERVER_MANAGER_LOG_ERROR("Failed to resurrect suspended server for %s", kAppName.c_str());
284 : }
285 1 : return false;
286 3 : }
287 :
288 48 : bool SessionServerAppManager::connectSessionServer(const std::shared_ptr<ISessionServerApp> &kSessionServer)
289 : {
290 48 : if (!kSessionServer)
291 : {
292 7 : RIALTO_SERVER_MANAGER_LOG_ERROR("Unable to connect Session Server - pointer is null!");
293 7 : return false;
294 : }
295 41 : if (!m_ipcController->createClient(kSessionServer->getServerId(), kSessionServer->getAppManagementSocketName()))
296 : {
297 2 : RIALTO_SERVER_MANAGER_LOG_ERROR("Failed to establish RialtoServerManager - RialtoSessionServer connection for "
298 : "session server with id: %d",
299 : kSessionServer->getServerId());
300 2 : kSessionServer->kill();
301 2 : if (m_healthcheckService)
302 : {
303 2 : m_healthcheckService->onServerRemoved(kSessionServer->getServerId());
304 : }
305 2 : m_sessionServerApps.erase(kSessionServer);
306 2 : return false;
307 : }
308 39 : RIALTO_SERVER_MANAGER_LOG_INFO("RialtoServerManager with id %d successfully connected",
309 : kSessionServer->getServerId());
310 39 : return true;
311 : }
312 :
313 14 : bool SessionServerAppManager::configureSessionServer(const std::shared_ptr<ISessionServerApp> &kSessionServer)
314 : {
315 14 : if (!kSessionServer)
316 : {
317 0 : RIALTO_SERVER_MANAGER_LOG_ERROR("Unable to configure Session Server - pointer is null!");
318 0 : return false;
319 : }
320 14 : if (kSessionServer->isNamedSocketInitialized())
321 : {
322 3 : return configureSessionServerWithSocketFd(kSessionServer);
323 : }
324 11 : return configureSessionServerWithSocketName(kSessionServer);
325 : }
326 :
327 6 : bool SessionServerAppManager::configurePreloadedSessionServer(
328 : const std::shared_ptr<ISessionServerApp> &kSessionServer, const std::string &appName,
329 : const firebolt::rialto::common::SessionServerState &state, const firebolt::rialto::common::AppConfig &appConfig,
330 : std::unique_ptr<firebolt::rialto::ipc::INamedSocket> &&namedSocket)
331 : {
332 6 : RIALTO_SERVER_MANAGER_LOG_INFO("Configuration of preloaded session server with id: %d for %s app",
333 : kSessionServer->getServerId(), appName.c_str());
334 11 : if (kSessionServer->configure(appName, state, appConfig, std::move(namedSocket)) &&
335 5 : configureSessionServer(kSessionServer))
336 : {
337 : // Schedule adding new preloaded session server (as we've just used one) and return immediately
338 8 : m_eventThread->add([this]() { connectSessionServer(preloadSessionServer()); });
339 4 : return true;
340 : }
341 : // Configuration failed, kill server and return error
342 2 : handleSessionServerStateChange(kSessionServer->getServerId(), firebolt::rialto::common::SessionServerState::ERROR);
343 2 : kSessionServer->kill();
344 2 : handleSessionServerStateChange(kSessionServer->getServerId(),
345 : firebolt::rialto::common::SessionServerState::NOT_RUNNING);
346 : // Schedule adding new preloaded session server
347 4 : m_eventThread->add([this]() { connectSessionServer(preloadSessionServer()); });
348 2 : return false;
349 : }
350 :
351 14 : bool SessionServerAppManager::changeSessionServerState(const std::string &appName,
352 : const firebolt::rialto::common::SessionServerState &newState)
353 : {
354 14 : RIALTO_SERVER_MANAGER_LOG_MIL("RialtoServerManager requests to change state of %s to %s", appName.c_str(),
355 : toString(newState));
356 14 : auto sessionServer{getServerByAppName(appName)};
357 14 : if (!sessionServer)
358 : {
359 2 : RIALTO_SERVER_MANAGER_LOG_ERROR("Change state of %s to %s failed - session server not found.", appName.c_str(),
360 : toString(newState));
361 2 : return false;
362 : }
363 12 : const firebolt::rialto::common::SessionServerState kCurrentState{sessionServer->getExpectedState()};
364 12 : sessionServer->setExpectedState(newState);
365 12 : if (kCurrentState == firebolt::rialto::common::SessionServerState::SUSPENDED &&
366 4 : (firebolt::rialto::common::SessionServerState::ACTIVE == newState ||
367 1 : firebolt::rialto::common::SessionServerState::INACTIVE == newState))
368 : {
369 3 : return resurrectSuspendedServer(sessionServer, newState);
370 : }
371 9 : else if (kCurrentState == firebolt::rialto::common::SessionServerState::SUSPENDED &&
372 1 : firebolt::rialto::common::SessionServerState::NOT_RUNNING == newState)
373 : {
374 : // Send the notification and do the cleanup only
375 1 : handleSessionServerStateChange(sessionServer->getServerId(), newState);
376 1 : return true;
377 : }
378 15 : else if (m_healthcheckService && (firebolt::rialto::common::SessionServerState::NOT_RUNNING == newState ||
379 15 : firebolt::rialto::common::SessionServerState::SUSPENDED == newState))
380 : {
381 6 : m_healthcheckService->onServerRemoved(sessionServer->getServerId());
382 : }
383 8 : if (!m_ipcController->performSetState(sessionServer->getServerId(), newState))
384 : {
385 2 : RIALTO_SERVER_MANAGER_LOG_ERROR("Change state of %s to %s failed.", appName.c_str(), toString(newState));
386 2 : handleStateChangeFailure(sessionServer, newState);
387 2 : return false;
388 : }
389 6 : RIALTO_SERVER_MANAGER_LOG_INFO("Change state of %s to %s succeeded.", appName.c_str(), toString(newState));
390 6 : return true;
391 14 : }
392 :
393 44 : void SessionServerAppManager::handleSessionServerStateChange(int serverId,
394 : firebolt::rialto::common::SessionServerState newState)
395 : {
396 44 : RIALTO_SERVER_MANAGER_LOG_INFO("SessionServer with id: %d changed state to %s", serverId, toString(newState));
397 44 : if (m_isShuttingDown)
398 : {
399 1 : RIALTO_SERVER_MANAGER_LOG_WARN("Not handling state change of serverId: %d as server manager is shutting down",
400 : serverId);
401 1 : return;
402 : }
403 43 : auto sessionServer{getServerById(serverId)};
404 43 : if (!sessionServer)
405 : {
406 0 : RIALTO_SERVER_MANAGER_LOG_WARN("SessionServer with id: %d not found", serverId);
407 0 : return;
408 : }
409 43 : std::string appName{sessionServer->getAppName()};
410 43 : if (!appName.empty() && m_stateObserver) // empty app name is when SessionServer is preloaded
411 : {
412 33 : m_stateObserver->stateChanged(appName, newState);
413 : }
414 43 : if (firebolt::rialto::common::SessionServerState::UNINITIALIZED == newState)
415 : {
416 15 : sessionServer->cancelStartupTimer();
417 15 : if (!sessionServer->isPreloaded() && !configureSessionServer(sessionServer))
418 : {
419 2 : handleSessionServerStateChange(serverId, firebolt::rialto::common::SessionServerState::ERROR);
420 2 : sessionServer->kill();
421 2 : handleSessionServerStateChange(serverId, firebolt::rialto::common::SessionServerState::NOT_RUNNING);
422 : }
423 : }
424 28 : else if (newState == firebolt::rialto::common::SessionServerState::ERROR && sessionServer->isPreloaded())
425 : {
426 1 : m_ipcController->removeClient(serverId);
427 1 : sessionServer->kill();
428 1 : if (m_healthcheckService)
429 : {
430 1 : m_healthcheckService->onServerRemoved(sessionServer->getServerId());
431 : }
432 1 : m_sessionServerApps.erase(sessionServer);
433 1 : if (!m_isShuttingDown)
434 : {
435 1 : connectSessionServer(preloadSessionServer());
436 : }
437 : }
438 27 : else if (newState == firebolt::rialto::common::SessionServerState::NOT_RUNNING)
439 : {
440 9 : m_ipcController->removeClient(serverId);
441 9 : if (m_healthcheckService)
442 : {
443 9 : m_healthcheckService->onServerRemoved(sessionServer->getServerId());
444 : }
445 9 : m_sessionServerApps.erase(sessionServer);
446 : }
447 18 : else if (newState == firebolt::rialto::common::SessionServerState::SUSPENDED)
448 : {
449 5 : m_ipcController->removeClient(sessionServer->getServerId());
450 5 : sessionServer->cleanup();
451 : }
452 43 : }
453 :
454 2 : void SessionServerAppManager::handleAck(int serverId, int pingId, bool success)
455 : {
456 2 : if (success)
457 : {
458 1 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Ping with id: %d succeeded for server: %d", pingId, serverId);
459 : }
460 : else
461 : {
462 1 : RIALTO_SERVER_MANAGER_LOG_ERROR("Ping with id: %d failed for server: %d", pingId, serverId);
463 : }
464 2 : if (m_healthcheckService)
465 : {
466 2 : m_healthcheckService->onAckReceived(serverId, pingId, success);
467 : }
468 : }
469 :
470 45 : void SessionServerAppManager::shutdownAllSessionServers()
471 : {
472 45 : setShuttingDown();
473 45 : m_healthcheckService.reset();
474 71 : for (const auto &kSessionServer : m_sessionServerApps)
475 : {
476 26 : kSessionServer->kill();
477 : }
478 45 : m_sessionServerApps.clear();
479 : }
480 :
481 : std::shared_ptr<ISessionServerApp>
482 31 : SessionServerAppManager::launchSessionServer(const std::string &appName,
483 : const firebolt::rialto::common::SessionServerState &kInitialState,
484 : const firebolt::rialto::common::AppConfig &appConfig)
485 : {
486 31 : RIALTO_SERVER_MANAGER_LOG_INFO("Launching Rialto Session Server for %s", appName.c_str());
487 31 : auto app = m_sessionServerAppFactory->create(appName, kInitialState, appConfig, *this,
488 31 : m_namedSocketFactory.createNamedSocket());
489 31 : if (app->launch())
490 : {
491 30 : if (m_sessionServerApps.emplace(app).second)
492 : {
493 30 : return app;
494 : }
495 : }
496 1 : return nullptr;
497 31 : }
498 :
499 15 : std::shared_ptr<ISessionServerApp> SessionServerAppManager::preloadSessionServer()
500 : {
501 15 : RIALTO_SERVER_MANAGER_LOG_INFO("Preloading new Rialto Session Server");
502 15 : auto app = m_sessionServerAppFactory->create(*this);
503 15 : if (app->launch())
504 : {
505 9 : if (m_sessionServerApps.emplace(app).second)
506 : {
507 9 : return app;
508 : }
509 : }
510 6 : return nullptr;
511 15 : }
512 :
513 39 : std::shared_ptr<ISessionServerApp> SessionServerAppManager::getPreloadedServer() const
514 : {
515 39 : auto iter = std::find_if(m_sessionServerApps.begin(), m_sessionServerApps.end(),
516 6 : [](const auto &srv) { return srv->isPreloaded() && srv->isConnected(); });
517 39 : if (m_sessionServerApps.end() != iter)
518 : {
519 6 : return *iter;
520 : }
521 33 : return nullptr;
522 : }
523 :
524 58 : std::shared_ptr<ISessionServerApp> SessionServerAppManager::getServerByAppName(const std::string &appName) const
525 : {
526 58 : auto iter{std::find_if(m_sessionServerApps.begin(), m_sessionServerApps.end(),
527 19 : [&](const auto &srv) { return srv->getAppName() == appName; })};
528 58 : if (m_sessionServerApps.end() != iter)
529 : {
530 14 : return *iter;
531 : }
532 44 : return nullptr;
533 : }
534 :
535 48 : std::shared_ptr<ISessionServerApp> SessionServerAppManager::getServerById(int serverId) const
536 : {
537 48 : auto iter{std::find_if(m_sessionServerApps.begin(), m_sessionServerApps.end(),
538 47 : [&](const auto &srv) { return srv->getServerId() == serverId; })};
539 48 : if (m_sessionServerApps.end() != iter)
540 : {
541 47 : return *iter;
542 : }
543 1 : return nullptr;
544 : }
545 :
546 2 : void SessionServerAppManager::handleStateChangeFailure(const std::shared_ptr<ISessionServerApp> &kSessionServer,
547 : const firebolt::rialto::common::SessionServerState &state)
548 : {
549 2 : if (state == firebolt::rialto::common::SessionServerState::NOT_RUNNING ||
550 1 : state == firebolt::rialto::common::SessionServerState::SUSPENDED)
551 : {
552 1 : RIALTO_SERVER_MANAGER_LOG_WARN("Force change of %s to NotRunning.", kSessionServer->getAppName().c_str());
553 1 : kSessionServer->kill();
554 1 : handleSessionServerStateChange(kSessionServer->getServerId(), state);
555 : }
556 : else
557 : {
558 1 : handleSessionServerStateChange(kSessionServer->getServerId(),
559 : firebolt::rialto::common::SessionServerState::ERROR);
560 : }
561 2 : }
562 :
563 11 : bool SessionServerAppManager::configureSessionServerWithSocketName(const std::shared_ptr<ISessionServerApp> &kSessionServer)
564 : {
565 11 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Configuring Session Server using socket name");
566 11 : const auto kInitialState{kSessionServer->getInitialState()};
567 11 : const auto kSocketName{kSessionServer->getSessionManagementSocketName()};
568 11 : const auto kClientDisplayName{kSessionServer->getClientDisplayName()};
569 11 : const auto kSocketPermissions{kSessionServer->getSessionManagementSocketPermissions()};
570 11 : const auto kSocketOwner{kSessionServer->getSessionManagementSocketOwner()};
571 11 : const auto kSocketGroup{kSessionServer->getSessionManagementSocketGroup()};
572 11 : const auto &kAppName{kSessionServer->getAppName()};
573 :
574 11 : const firebolt::rialto::common::MaxResourceCapabilitites kMaxResource{kSessionServer->getMaxPlaybackSessions(),
575 11 : kSessionServer->getMaxWebAudioPlayers()};
576 11 : if (!m_ipcController->performSetConfiguration(kSessionServer->getServerId(), kInitialState, kSocketName,
577 : kClientDisplayName, kMaxResource, kSocketPermissions, kSocketOwner,
578 : kSocketGroup, kAppName))
579 : {
580 2 : RIALTO_SERVER_MANAGER_LOG_ERROR("Configuration of server with id %d failed - ipc error.",
581 : kSessionServer->getServerId());
582 2 : return false;
583 : }
584 9 : RIALTO_SERVER_MANAGER_LOG_INFO("Configuration of server with id %d succeeded.", kSessionServer->getServerId());
585 9 : return true;
586 11 : }
587 :
588 3 : bool SessionServerAppManager::configureSessionServerWithSocketFd(const std::shared_ptr<ISessionServerApp> &kSessionServer)
589 : {
590 3 : RIALTO_SERVER_MANAGER_LOG_DEBUG("Configuring Session Server using socket fd");
591 3 : const auto kInitialState{kSessionServer->getInitialState()};
592 3 : const auto kSocketFd{kSessionServer->getSessionManagementSocketFd()};
593 3 : const auto kClientDisplayName{kSessionServer->getClientDisplayName()};
594 3 : const auto &kAppName{kSessionServer->getAppName()};
595 :
596 3 : const firebolt::rialto::common::MaxResourceCapabilitites kMaxResource{kSessionServer->getMaxPlaybackSessions(),
597 3 : kSessionServer->getMaxWebAudioPlayers()};
598 3 : if (!m_ipcController->performSetConfiguration(kSessionServer->getServerId(), kInitialState, kSocketFd,
599 : kClientDisplayName, kMaxResource, kAppName))
600 : {
601 1 : RIALTO_SERVER_MANAGER_LOG_ERROR("Configuration of server with id %d failed - ipc error.",
602 : kSessionServer->getServerId());
603 1 : return false;
604 : }
605 2 : RIALTO_SERVER_MANAGER_LOG_INFO("Configuration of server with id %d succeeded.", kSessionServer->getServerId());
606 2 : return true;
607 3 : }
608 :
609 2 : void SessionServerAppManager::onServerStartupTimeout(int serverId)
610 : {
611 2 : m_eventThread->add(&SessionServerAppManager::handleServerStartupTimeout, this, serverId);
612 : }
613 :
614 2 : void SessionServerAppManager::handleServerStartupTimeout(int serverId)
615 : {
616 2 : auto sessionServer{getServerById(serverId)};
617 2 : if (!sessionServer)
618 : {
619 1 : RIALTO_SERVER_MANAGER_LOG_WARN("Unable to handle startup timeout for serverId: %d", serverId);
620 1 : return;
621 : }
622 1 : const bool isPreloaded{sessionServer->isPreloaded()};
623 1 : RIALTO_SERVER_MANAGER_LOG_WARN("Killing: %d", serverId);
624 1 : handleSessionServerStateChange(serverId, firebolt::rialto::common::SessionServerState::ERROR);
625 :
626 1 : if (!isPreloaded)
627 : {
628 1 : if (m_healthcheckService)
629 : {
630 1 : m_healthcheckService->onServerRemoved(sessionServer->getServerId());
631 : }
632 1 : sessionServer->kill();
633 1 : handleSessionServerStateChange(serverId, firebolt::rialto::common::SessionServerState::NOT_RUNNING);
634 : }
635 2 : }
636 : } // namespace rialto::servermanager::common
|