Skip to content

Commit

Permalink
[Webserver]: Implement suspend resume for WebServer (#829)
Browse files Browse the repository at this point in the history
* Implementing Suspend and Resume for webserver

* Merge with rdkcentral:master branch

* Addressing review comment to remove IWeb

* Addressing code review comments

* fix: Fix for compilation error

* code cleanup

* Sending notification about state change

---------

Co-authored-by: Pierre Wielders <pierre@wielders.net>
  • Loading branch information
Karthick-Somasundaresan and pwielders authored Sep 19, 2024
1 parent 6787640 commit 20ad98d
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 19 deletions.
30 changes: 30 additions & 0 deletions WebServer/WebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ namespace Plugin {
message = _T("WebServer Couldnt get StateControl.");

} else {
stateControl->Register(&_notification);
uint32_t result = stateControl->Configure(_service);
stateControl->Release();
if (result != Core::ERROR_NONE) {
Expand Down Expand Up @@ -163,5 +164,34 @@ namespace Plugin {
Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE));
}
}
void WebServer::StateChange(const PluginHost::IStateControl::state state)
{
switch (state) {
case PluginHost::IStateControl::RESUMED:
TRACE(Trace::Information,
(string(_T("StateChange: { \"suspend\":false }"))));
_service->Notify("{ \"suspended\":false }");
break;
case PluginHost::IStateControl::SUSPENDED:
TRACE(Trace::Information,
(string(_T("StateChange: { \"suspend\":true }"))));
_service->Notify("{ \"suspended\":true }");
break;
case PluginHost::IStateControl::EXITED:
Core::IWorkerPool::Instance().Submit(
PluginHost::IShell::Job::Create(_service,
PluginHost::IShell::DEACTIVATED,
PluginHost::IShell::REQUESTED));
break;
case PluginHost::IStateControl::UNINITIALIZED:
break;
default:
ASSERT(false);
break;
}
}



}
}
11 changes: 9 additions & 2 deletions WebServer/WebServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
namespace Thunder {
namespace Plugin {

class WebServer : public PluginHost::IPlugin {
class WebServer : public PluginHost::IPlugin{
private:

class Notification : public RPC::IRemoteConnection::INotification {
class Notification : public RPC::IRemoteConnection::INotification, public PluginHost::IStateControl::INotification {
public:
Notification() = delete;
Notification(const Notification&) = delete;
Expand All @@ -56,8 +56,14 @@ namespace Plugin {
{
}


void StateChange(const PluginHost::IStateControl::state state) override {
_parent.StateChange(state);
}

BEGIN_INTERFACE_MAP(Notification)
INTERFACE_ENTRY(RPC::IRemoteConnection::INotification)
INTERFACE_ENTRY (PluginHost::IStateControl::INotification)
END_INTERFACE_MAP

private:
Expand Down Expand Up @@ -108,6 +114,7 @@ POP_WARNING()
// to this plugin. This Metadata can be used by the MetData plugin to publish this information to the ouside world.
string Information() const override;

void StateChange(PluginHost::IStateControl::state);
private:
void Deactivated(RPC::IRemoteConnection* connection);

Expand Down
80 changes: 63 additions & 17 deletions WebServer/WebServerImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ namespace Plugin {
RUNNING
};
class ChannelMap;

class WebFlow {
public:
WebFlow(const WebFlow& a_Copy) = delete;
Expand Down Expand Up @@ -521,6 +520,12 @@ PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST)
POP_WARNING()
~ChannelMap()
{
BaseClass::Iterator index(BaseClass::Clients());
ASSERT(index.Count() == 0);
}

public:
void CloseAndCleanupConnections() {
// Start by closing the server thread..
Core::SocketServerType<IncomingChannel>::Close(1000);

Expand All @@ -536,8 +541,6 @@ POP_WARNING()
// Cleanup the closed sockets we created..
Cleanup();
}

public:
uint32_t Configure(const string& prefixPath, const Config& configuration)
{
Core::NodeId accessor;
Expand All @@ -551,7 +554,7 @@ POP_WARNING()
_prefixPath.clear();
}
else if (configuration.Path.Value()[0] == '/') {
_prefixPath = Core::Directory::Normalize(configuration.Path.Value());
_prefixPath = Core::Directory::Normalize(configuration.Path.Value());
}
else {
_prefixPath = prefixPath + Core::Directory::Normalize(configuration.Path.Value());
Expand Down Expand Up @@ -706,35 +709,73 @@ POP_WARNING()

WebServerImplementation()
: _channelServer()
, _adminLock()
, _observers()
, _state(PluginHost::IStateControl::UNINITIALIZED)
, _requestedCommand(PluginHost::IStateControl::SUSPEND)
, _job(*this)
{
}

~WebServerImplementation() override = default;
~WebServerImplementation() override {
for (auto & observer: _observers){
Unregister(observer);
}
}

friend Core::ThreadPool::JobType<WebServerImplementation&>;

uint32_t Configure(PluginHost::IShell* service) override
{
ASSERT(service != nullptr);

Config config;
config.FromString(service->ConfigLine());

uint32_t result(_channelServer.Configure(service->DataPath(), config));

if (result == Core::ERROR_NONE) {

result = _channelServer.Open(2000);
}

uint32_t result = _channelServer.Configure(service->DataPath(), config);
return (result);
}
PluginHost::IStateControl::state State() const override
{
return (PluginHost::IStateControl::RESUMED);
PluginHost::IStateControl::state state;
_adminLock.Lock();
state = _state;
_adminLock.Unlock();
return state;
}
uint32_t Request(const PluginHost::IStateControl::command) override


void Dispatch() {
bool stateChanged = false;
uint32_t result = Core::ERROR_NONE;
_adminLock.Lock();
if(_requestedCommand == PluginHost::IStateControl::RESUME ) {
if ((_state == PluginHost::IStateControl::UNINITIALIZED || _state == PluginHost::IStateControl::SUSPENDED)) {
result = _channelServer.Open(2000);
if ( result == Core::ERROR_NONE) {
stateChanged = true;
_state = PluginHost::IStateControl::RESUMED;
}
}
} else {
if(_state == PluginHost::IStateControl::RESUMED || _state == PluginHost::IStateControl::UNINITIALIZED ) {
_channelServer.CloseAndCleanupConnections();
stateChanged = true;
_state = PluginHost::IStateControl::SUSPENDED;
}
}
if(stateChanged) {
for(auto& observer: _observers) {
observer->StateChange(_state);
}
}
_adminLock.Unlock();
}

uint32_t Request(const PluginHost::IStateControl::command command) override
{
// No state can be set, we can only move from ININITIALIZED to RUN...
_adminLock.Lock();
_requestedCommand = command;
_job.Submit();
_adminLock.Unlock();
return (Core::ERROR_NONE);
}

Expand Down Expand Up @@ -789,7 +830,12 @@ POP_WARNING()

private:
ChannelMap _channelServer;
mutable Core::CriticalSection _adminLock;
std::list<PluginHost::IStateControl::INotification*> _observers;
PluginHost::IStateControl::state _state;
PluginHost::IStateControl::command _requestedCommand;
Core::WorkerPool::JobType<WebServerImplementation&> _job;

};

SERVICE_REGISTRATION(WebServerImplementation, 1, 0)
Expand Down

0 comments on commit 20ad98d

Please sign in to comment.