Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RDK-47153 Support Hibernate options 'dest' and 'compress' #356

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ cmake -DCMAKE_BUILD_TYPE=Debug -DRDK_PLATFORM=DEV_VM -DCMAKE_INSTALL_PREFIX:PATH
| `-DUSE_SYSTEMD` | ON/OFF | Build with systemd support (recommended). When disabled, uses libdbus API instead of sd-bus. Defaults to ON. |
| `-DEXTERNAL_PLUGIN_SCHEMA` | Valid file path(s) | Path(s) to external json schema definitions for extra rdk plugins. Paths should be seperated by `;`. |
| `-DENABLE_OPT_SETTINGS` | ON/OFF | Enable searching for dobby.json settings in /opt/ directory. Defaults to OFF. |
| `-DDOBBY_HIBERNATE_MEMCR_IMPL` | ON/OFF | Hibernate container using [memcr](https://github.com/LibertyGlobal/memcr) service. Defaults to OFF. |
| `-DDOBBY_HIBERNATE_MEMCR_PARAMS_ENABLED` | ON/OFF | Enable support for hibernate parameters in [memcr](https://github.com/LibertyGlobal/memcr) service. Defaults to OFF. |

#### Enable/Disable Plugins
In addition to all the above, each RDK plugin has a setting for enabling it for builds. The `Logging`, `Networking`, `IPC`, `Storage` and `Minidump` plugins are enabled by default.
Expand Down
12 changes: 7 additions & 5 deletions client/tool/source/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,15 +510,17 @@ static void hibernateCommand(const std::shared_ptr<IDobbyProxy>& dobbyProxy,
size_t i = 0;
std::string options;

// Find options from arguments (start with a '-')
while (args[i].c_str()[0] == '-')
// Find options from arguments (start with a '--')
while (args[i].length() > 1 && args[i].c_str()[0] == '-' && args[i].c_str()[1] == '-')
{
// Add space between options
// strip off the '--'
std::string arg(args[i].c_str() + 2);
// Add comma between options
if (!options.empty())
{
options.append(" ");
options.append(",");
}
options.append(args[i]);
options.append(arg);
i++;
}

Expand Down
5 changes: 5 additions & 0 deletions daemon/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# limitations under the License.

option(DOBBY_HIBERNATE_MEMCR_IMPL "Hibernate containers using Memcr tool" OFF)
option(DOBBY_HIBERNATE_MEMCR_PARAMS_ENABLED "Enable optional parameters in Memcr protocol" OFF)

if (LEGACY_COMPONENTS)
list(APPEND ADDITIONAL_SOURCES
Expand Down Expand Up @@ -100,6 +101,10 @@ endif()

if(DOBBY_HIBERNATE_MEMCR_IMPL)
add_definitions( -DDOBBY_HIBERNATE_MEMCR_IMPL=1 )

if (DOBBY_HIBERNATE_MEMCR_PARAMS_ENABLED)
add_definitions( -DDOBBY_HIBERNATE_MEMCR_PARAMS_ENABLED=1 )
endif()
endif()

# Install public headers for external use
Expand Down
88 changes: 76 additions & 12 deletions daemon/lib/source/DobbyHibernate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,20 @@

typedef enum {
MEMCR_CHECKPOINT = 100,
MEMCR_RESTORE
MEMCR_RESTORE,
MEMCR_CMDS_V2
} ServerRequestCode;

typedef enum {
MEMCR_CHECKPOINT_DUMPDIR = 200,
MEMCR_CHECKPOINT_COMPRESS_ALG,
} ServerRequestCodeOptions;

typedef struct {
std::string dumpDir;
DobbyHibernate::CompressionAlg compressAlg;
} ServerRequestOptions;

typedef enum {
MEMCR_OK = 0,
MEMCR_ERROR = -1,
Expand All @@ -56,9 +67,12 @@ typedef struct {
ServerResponseCode respCode;
} __attribute__((packed)) ServerResponse;

const char* DobbyHibernate::DFL_LOCATOR = "/tmp/memcrcom";
const std::string DobbyHibernate::DFL_LOCATOR = "/tmp/memcrcom";
const uint32_t DobbyHibernate::DFL_TIMEOUTE_MS = 20000;

#define MEMCR_DUMPDIR_LEN_MAX 1024
#define CMD_LEN_MAX (sizeof(ServerRequest) + (2*sizeof(ServerRequestCodeOptions)) + MEMCR_DUMPDIR_LEN_MAX + 1)


static int Connect(const char* serverLocator, uint32_t timeoutMs)
{
Expand Down Expand Up @@ -138,11 +152,12 @@ static int Connect(const char* serverLocator, uint32_t timeoutMs)
return cd;
}

static bool SendRcvCmd(const ServerRequest* cmd, ServerResponse* resp, uint32_t timeoutMs, const char* serverLocator)
static bool SendRcvCmd(const ServerRequest* cmd, ServerResponse* resp, uint32_t timeoutMs, const char* serverLocator, const ServerRequestOptions *opt)
{
AI_LOG_FN_ENTRY();
int cd;
int ret;

resp->respCode = MEMCR_ERROR;

cd = Connect(serverLocator, timeoutMs);
Expand All @@ -152,13 +167,58 @@ static bool SendRcvCmd(const ServerRequest* cmd, ServerResponse* resp, uint32_t
return false;
}

#ifdef DOBBY_HIBERNATE_MEMCR_PARAMS_ENABLED
int cmdSize = 0;
unsigned char cmdBuf[CMD_LEN_MAX];

memcpy(cmdBuf, cmd, sizeof(ServerRequest));
cmdSize += sizeof(ServerRequest);

if (opt) {
if (opt->dumpDir.length() > 0) {
ServerRequestCodeOptions optId = MEMCR_CHECKPOINT_DUMPDIR;
memcpy(cmdBuf + cmdSize, &optId, sizeof(ServerRequestCodeOptions));
cmdSize += sizeof(ServerRequestCodeOptions);
strncpy((char *)cmdBuf + cmdSize, opt->dumpDir.c_str(), MEMCR_DUMPDIR_LEN_MAX);
cmdSize += opt->dumpDir.length() + 1;
}

if (opt->compressAlg != DobbyHibernate::CompressionAlg::AlgDefault) {
ServerRequestCodeOptions optId = MEMCR_CHECKPOINT_COMPRESS_ALG;
memcpy(cmdBuf + cmdSize, &optId, sizeof(ServerRequestCodeOptions));
cmdSize += sizeof(ServerRequestCodeOptions);
memcpy(cmdBuf + cmdSize, &opt->compressAlg, sizeof(DobbyHibernate::CompressionAlg));
cmdSize += sizeof(DobbyHibernate::CompressionAlg);
}
}

ServerRequest cmdV2 = {.reqCode = MEMCR_CMDS_V2, .pid = cmdSize};

ret = write(cd, &cmdV2, sizeof(ServerRequest));
if (ret != sizeof(ServerRequest)) {
AI_LOG_ERROR("Socket write failed: ret %d, %m", ret);
close(cd);
AI_LOG_FN_EXIT();
return false;
}

ret = write(cd, cmdBuf, cmdSize);
if (ret != cmdSize) {
AI_LOG_ERROR("Socket write failed: ret %d, %m", ret);
close(cd);
AI_LOG_FN_EXIT();
return false;
}

#else
ret = write(cd, cmd, sizeof(ServerRequest));
if (ret != sizeof(ServerRequest)) {
AI_LOG_ERROR("Socket write failed: ret %d, %m", ret);
close(cd);
AI_LOG_FN_EXIT();
return false;
}
#endif

ret = read(cd, resp, sizeof(ServerResponse));
if (ret != sizeof(ServerResponse)) {
Expand All @@ -175,17 +235,21 @@ static bool SendRcvCmd(const ServerRequest* cmd, ServerResponse* resp, uint32_t
return (resp->respCode == MEMCR_OK);
}

DobbyHibernate::Error DobbyHibernate::HibernateProcess(const pid_t pid, const uint32_t timeout, const char* locator,
const char* dumpDirPath, CompressionAlg compression)
DobbyHibernate::Error DobbyHibernate::HibernateProcess(const pid_t pid, const uint32_t timeout, const std::string &locator,
const std::string &dumpDirPath, CompressionAlg compression)
{
AI_LOG_FN_ENTRY();
ServerRequest req = {
.reqCode = MEMCR_CHECKPOINT,
.pid = pid
};
ServerRequestOptions opt = {
.dumpDir = dumpDirPath,
.compressAlg = compression
};
ServerResponse resp;

if (SendRcvCmd(&req, &resp, timeout, locator)) {
if (SendRcvCmd(&req, &resp, timeout, locator.c_str(), &opt)) {
AI_LOG_INFO("Hibernate process PID %d success", pid);
AI_LOG_FN_EXIT();
return DobbyHibernate::Error::ErrorNone;
Expand All @@ -200,7 +264,7 @@ DobbyHibernate::Error DobbyHibernate::HibernateProcess(const pid_t pid, const ui
}
}

DobbyHibernate::Error DobbyHibernate::WakeupProcess(const pid_t pid, const uint32_t timeout, const char* locator)
DobbyHibernate::Error DobbyHibernate::WakeupProcess(const pid_t pid, const uint32_t timeout, const std::string &locator)
{
AI_LOG_FN_ENTRY();
ServerRequest req = {
Expand All @@ -209,7 +273,7 @@ DobbyHibernate::Error DobbyHibernate::WakeupProcess(const pid_t pid, const uint3
};
ServerResponse resp;

if (SendRcvCmd(&req, &resp, timeout, locator)) {
if (SendRcvCmd(&req, &resp, timeout, locator.c_str(), nullptr)) {
AI_LOG_INFO("Wakeup process PID %d success", pid);
AI_LOG_FN_EXIT();
return DobbyHibernate::Error::ErrorNone;
Expand All @@ -226,17 +290,17 @@ DobbyHibernate::Error DobbyHibernate::WakeupProcess(const pid_t pid, const uint3

#else

const char* DobbyHibernate::DFL_LOCATOR = "";
const std::string DobbyHibernate::DFL_LOCATOR = "";
const uint32_t DobbyHibernate::DFL_TIMEOUTE_MS = 0;

DobbyHibernate::Error DobbyHibernate::HibernateProcess(const pid_t pid, const uint32_t timeout, const char* locator,
const char* dumpDirPath, CompressionAlg compression)
DobbyHibernate::Error DobbyHibernate::HibernateProcess(const pid_t pid, const uint32_t timeout, const std::string &locator,
const std::string &dumpDirPath, CompressionAlg compression)
{
AI_LOG_ERROR("DobbyHibernate Implementation not enabled");
return DobbyHibernate::Error::ErrorGeneral;
}

DobbyHibernate::Error DobbyHibernate::WakeupProcess(const pid_t pid, const uint32_t timeout, const char* locator)
DobbyHibernate::Error DobbyHibernate::WakeupProcess(const pid_t pid, const uint32_t timeout, const std::string &locator)
{
AI_LOG_ERROR("DobbyHibernate Implementation not enabled");
return DobbyHibernate::Error::ErrorGeneral;
Expand Down
10 changes: 6 additions & 4 deletions daemon/lib/source/DobbyHibernate.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <sys/types.h>
#include <stdint.h>
#include <string>

class DobbyHibernate
{
Expand All @@ -40,14 +41,15 @@ class DobbyHibernate
{
AlgNone = 0,
AlgLz4 = 1,
AlgZstd = 2
AlgZstd = 2,
AlgDefault = 3
};

static const char* DFL_LOCATOR;
static const std::string DFL_LOCATOR;
static const uint32_t DFL_TIMEOUTE_MS;

static Error HibernateProcess(const pid_t pid, const uint32_t timeout = DFL_TIMEOUTE_MS,
const char* locator = DFL_LOCATOR, const char* dumpDirPath = nullptr, CompressionAlg compression = AlgLz4);
const std::string &locator = DFL_LOCATOR, const std::string &dumpDirPath = std::string(), CompressionAlg compression = AlgDefault);

static Error WakeupProcess(const pid_t pid, const uint32_t timeout = DFL_TIMEOUTE_MS, const char* locator = DFL_LOCATOR);
static Error WakeupProcess(const pid_t pid, const uint32_t timeout = DFL_TIMEOUTE_MS, const std::string &locator = DFL_LOCATOR);
};
51 changes: 50 additions & 1 deletion daemon/lib/source/DobbyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,54 @@ bool DobbyManager::hibernateContainer(int32_t cd, const std::string& options)
return false;
}

// parse options: dest, compress
// format: dest=/some/path/blah,compress=lz4
std::string dest;
DobbyHibernate::CompressionAlg compress = DobbyHibernate::CompressionAlg::AlgDefault;

// lambda to split a string by a delimiter
auto splitString = [](const std::string& str, char delimiter) -> std::vector<std::string>
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(str);
while (std::getline(tokenStream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
};

AI_LOG_INFO("Hibernation options: %s", options.c_str());

std::vector<std::string> optionList = splitString(options, ',');
for (const std::string& option : optionList)
{
std::vector<std::string> keyValue = splitString(option, '=');
if (keyValue.size() == 2)
{
if (keyValue[0] == "dest")
{
dest = keyValue[1];
}
else if (keyValue[0] == "compress")
{
if (keyValue[1] == "lz4")
{
compress = DobbyHibernate::CompressionAlg::AlgLz4;
}
else if (keyValue[1] == "zstd")
{
compress = DobbyHibernate::CompressionAlg::AlgZstd;
}
else
{
AI_LOG_WARN("Unsupported compression algorithm: %s", keyValue[1].c_str());
}
}
}
}

std::thread hibernateThread =
std::thread([=]()
{
Expand All @@ -1597,7 +1645,8 @@ bool DobbyManager::hibernateContainer(int32_t cd, const std::string& options)
locker.unlock();

uint32_t pid = pidIt->asUInt();
ret = DobbyHibernate::HibernateProcess(pid);
ret = DobbyHibernate::HibernateProcess(pid, DobbyHibernate::DFL_TIMEOUTE_MS,
DobbyHibernate::DFL_LOCATOR, dest, compress);
if (ret != DobbyHibernate::Error::ErrorNone)
{
AI_LOG_WARN("Error hibernating pid: '%d'", pid);
Expand Down
Loading