LCOV - code coverage report
Current view: top level - serverManager/common/source - SessionServerAppManager.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 96.3 % 356 343
Test Date: 2026-10-23 12:56:16 Functions: 100.0 % 43 43

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

Generated by: LCOV version 2.0-1