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 2023 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 "ControlServerInternal.h"
21 : #include "RialtoServerLogging.h"
22 : #include <stdexcept>
23 :
24 : namespace
25 : {
26 9 : const char *convertApplicationState(const firebolt::rialto::ApplicationState &appState)
27 : {
28 9 : switch (appState)
29 : {
30 0 : case firebolt::rialto::ApplicationState::UNKNOWN:
31 0 : return "UNKNOWN";
32 7 : case firebolt::rialto::ApplicationState::RUNNING:
33 7 : return "RUNNING";
34 2 : case firebolt::rialto::ApplicationState::INACTIVE:
35 2 : return "INACTIVE";
36 : }
37 0 : return "UNKNOWN";
38 : }
39 : } // namespace
40 :
41 : namespace firebolt::rialto
42 : {
43 1 : std::shared_ptr<IControlFactory> IControlFactory::createFactory()
44 : {
45 1 : return server::IControlServerInternalFactory::createFactory();
46 : }
47 : } // namespace firebolt::rialto
48 :
49 : namespace firebolt::rialto::server
50 : {
51 1 : std::shared_ptr<IControlServerInternalFactory> IControlServerInternalFactory::createFactory()
52 : try
53 : {
54 1 : return std::make_shared<ControlServerInternalFactory>();
55 : }
56 0 : catch (std::exception &e)
57 : {
58 0 : RIALTO_SERVER_LOG_ERROR("ControlServerInternalFactory creation failed");
59 0 : return nullptr;
60 : }
61 :
62 1 : std::shared_ptr<IControl> ControlServerInternalFactory::createControl() const
63 : {
64 1 : RIALTO_SERVER_LOG_ERROR("This function can't be used by rialto server. Please use createControlServerInternal");
65 1 : return nullptr;
66 : }
67 :
68 0 : std::shared_ptr<IControlServerInternal> ControlServerInternalFactory::createControlServerInternal(
69 : int id, const std::shared_ptr<IControlClientServerInternal> &client) const
70 : try
71 : {
72 0 : return std::make_shared<ControlServerInternal>(server::IMainThreadFactory::createFactory(), id, client);
73 : }
74 0 : catch (const std::exception &e)
75 : {
76 0 : RIALTO_SERVER_LOG_ERROR("ControlServerInternal creation failed");
77 0 : return nullptr;
78 : }
79 :
80 11 : ControlServerInternal::ControlServerInternal(const std::shared_ptr<IMainThreadFactory> &mainThreadFactory, int id,
81 11 : const std::shared_ptr<IControlClientServerInternal> &client)
82 11 : : m_controlId{id}, m_client{client}, m_currentState{ApplicationState::UNKNOWN}
83 : {
84 11 : RIALTO_SERVER_LOG_DEBUG("entry:");
85 11 : m_mainThread = mainThreadFactory->getMainThread();
86 11 : if (!m_mainThread)
87 : {
88 0 : throw std::runtime_error("Failed to get the main thread");
89 : }
90 11 : m_mainThreadClientId = m_mainThread->registerClient();
91 : }
92 :
93 22 : ControlServerInternal::~ControlServerInternal()
94 : {
95 11 : RIALTO_SERVER_LOG_DEBUG("entry:");
96 11 : m_mainThread->unregisterClient(m_mainThreadClientId);
97 22 : }
98 :
99 5 : void ControlServerInternal::ack(int32_t ackId)
100 : {
101 5 : RIALTO_SERVER_LOG_DEBUG("Control with id: %d received ack for ping: %d", m_controlId, ackId);
102 5 : auto task = [&]()
103 : {
104 5 : if (!m_heartbeatHandler)
105 : {
106 1 : RIALTO_SERVER_LOG_WARN("No heartbeatHandler present for control with id: %d", m_controlId);
107 1 : return;
108 : }
109 4 : if (m_heartbeatHandler->id() != ackId)
110 : {
111 1 : RIALTO_SERVER_LOG_WARN("Control with id: %d received ack with wrong id: %d", m_controlId, ackId);
112 1 : return;
113 : }
114 3 : m_heartbeatHandler.reset();
115 5 : };
116 5 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
117 : }
118 :
119 9 : void ControlServerInternal::setApplicationState(const ApplicationState &state)
120 : {
121 9 : RIALTO_SERVER_LOG_INFO("Notify rialto client about state changed to: %s", convertApplicationState(state));
122 9 : auto task = [&]()
123 : {
124 27 : m_currentState = state;
125 9 : if (m_client)
126 9 : m_client->notifyApplicationState(state);
127 18 : };
128 9 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
129 : }
130 :
131 11 : void ControlServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
132 : {
133 11 : RIALTO_SERVER_LOG_DEBUG("Control with id: %d will send ping with id: %d", m_controlId, heartbeatHandler->id());
134 11 : auto task = [&]()
135 : {
136 11 : if (m_currentState != ApplicationState::RUNNING)
137 : {
138 3 : RIALTO_SERVER_LOG_DEBUG("Control with id: %d in INACTIVE state. Ack immediately for ping with id: %d",
139 : m_controlId, heartbeatHandler->id());
140 3 : m_heartbeatHandler.reset();
141 3 : heartbeatHandler.reset();
142 3 : return;
143 : }
144 8 : if (m_heartbeatHandler)
145 : {
146 1 : m_heartbeatHandler->error();
147 1 : m_heartbeatHandler.reset();
148 : }
149 8 : if (m_client)
150 : {
151 8 : m_client->ping(heartbeatHandler->id());
152 8 : m_heartbeatHandler = std::move(heartbeatHandler);
153 : }
154 11 : };
155 11 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
156 : }
157 :
158 0 : bool ControlServerInternal::registerClient(std::weak_ptr<IControlClient> client, ApplicationState &appState)
159 : {
160 0 : RIALTO_SERVER_LOG_ERROR("Method not implemented");
161 0 : return false;
162 : }
163 : } // namespace firebolt::rialto::server
|