aboutsummaryrefslogtreecommitdiff
path: root/host
diff options
context:
space:
mode:
authorSteve Kim <kwstephenkim@google.com>2023-04-14 18:33:02 -0700
committerSteve Kim <kwstephenkim@google.com>2023-04-20 17:16:22 -0700
commitd79ae01ba085612959283b7881283d92806352c2 (patch)
tree428a8f9f8a85276595d8a1737e38f9bdec023df2 /host
parent8a429379987033bc134f458ef0ecb0ef0b71a9bc (diff)
downloadcuttlefish-d79ae01ba085612959283b7881283d92806352c2.tar.gz
Save in-memory data to a memory file
The restart-server handler and the server should implement functions to save the in-memory data in a memory file. Bug: 232028559 Test: cvd version && cvd restart-server Change-Id: Ic7e8351acad19cb58287a4e74fddbd8a006c2dd1
Diffstat (limited to 'host')
-rw-r--r--host/commands/cvd/server.cc13
-rw-r--r--host/commands/cvd/server.h3
-rw-r--r--host/commands/cvd/server_command/restart.cpp41
3 files changed, 49 insertions, 8 deletions
diff --git a/host/commands/cvd/server.cc b/host/commands/cvd/server.cc
index 407801323..e73f3b8e8 100644
--- a/host/commands/cvd/server.cc
+++ b/host/commands/cvd/server.cc
@@ -469,4 +469,17 @@ Result<int> CvdServerMain(SharedFD server_fd, SharedFD carryover_client) {
return 0;
}
+Result<std::string> ReadAllFromMemFd(const SharedFD& mem_fd) {
+ const auto n_message_size = mem_fd->LSeek(0, SEEK_END);
+ CF_EXPECT_NE(n_message_size, -1, "LSeek on the memory file failed.");
+ std::vector<char> buffer(n_message_size);
+ CF_EXPECT_EQ(mem_fd->LSeek(0, SEEK_SET), 0, mem_fd->StrError());
+ auto n_read = ReadExact(mem_fd, buffer.data(), n_message_size);
+ CF_EXPECT(n_read == n_message_size,
+ "Expected to read " << n_message_size << " bytes but actually read "
+ << n_read << " bytes.");
+ std::string message(buffer.begin(), buffer.end());
+ return message;
+}
+
} // namespace cuttlefish
diff --git a/host/commands/cvd/server.h b/host/commands/cvd/server.h
index de7ca02b3..d6dd79ed9 100644
--- a/host/commands/cvd/server.h
+++ b/host/commands/cvd/server.h
@@ -93,4 +93,7 @@ Result<CvdServerHandler*> RequestHandler(
Result<int> CvdServerMain(SharedFD server_fd, SharedFD carryover_client);
+// Read all contents from the file
+Result<std::string> ReadAllFromMemFd(const SharedFD& mem_fd);
+
} // namespace cuttlefish
diff --git a/host/commands/cvd/server_command/restart.cpp b/host/commands/cvd/server_command/restart.cpp
index 4c005095e..122df8d2b 100644
--- a/host/commands/cvd/server_command/restart.cpp
+++ b/host/commands/cvd/server_command/restart.cpp
@@ -18,18 +18,20 @@
#include <sys/types.h>
+#include <cstdio>
#include <iostream>
#include <android-base/file.h>
-#include <android-base/strings.h>
#include <fruit/fruit.h>
#include "cvd_server.pb.h"
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/contains.h"
#include "common/libs/utils/result.h"
-#include "host/commands/cvd/flag.h"
+#include "host/commands/cvd/common_utils.h"
+#include "host/commands/cvd/epoll_loop.h"
#include "host/commands/cvd/frontline_parser.h"
#include "host/commands/cvd/instance_manager.h"
#include "host/commands/cvd/server_command/components.h"
@@ -42,6 +44,7 @@ namespace {
constexpr char kRestartServerHelpMessage[] =
R"(Cuttlefish Virtual Device (CVD) CLI.
+
usage: cvd restart-server <common args> <mode> <mode args>
Common Args:
@@ -101,11 +104,7 @@ class CvdRestartHandler : public CvdServerHandler {
Result<cvd::Response> Handle(const RequestWithStdio& request) override {
CF_EXPECT(CanHandle(request));
- CF_EXPECT(request.Credentials() != std::nullopt);
- const uid_t uid = request.Credentials()->uid;
cvd::Response response;
- response.mutable_shutdown_response();
-
if (request.Message().has_shutdown_request()) {
response.mutable_shutdown_response();
} else {
@@ -130,7 +129,7 @@ class CvdRestartHandler : public CvdServerHandler {
return response;
}
- if (instance_manager_.HasInstanceGroups(uid)) {
+ if (instance_manager_.HasInstanceGroups(getuid())) {
response.mutable_status()->set_code(cvd::Status::FAILED_PRECONDITION);
response.mutable_status()->set_message(
"Cannot restart cvd_server while devices are being tracked. "
@@ -138,9 +137,19 @@ class CvdRestartHandler : public CvdServerHandler {
return response;
}
+ // On CF_ERR, the locks will be released automatically
WriteAll(request.Out(), "Stopping the cvd_server.\n");
server_.Stop();
+ CF_EXPECT(request.Credentials() != std::nullopt);
+ const uid_t client_uid = request.Credentials()->uid;
+ auto json_string =
+ CF_EXPECT(SerializedInstanceDatabaseToString(client_uid));
+ std::optional<SharedFD> mem_fd;
+ if (instance_manager_.HasInstanceGroups(client_uid)) {
+ mem_fd = CF_EXPECT(CreateMemFileWithSerializedDb(json_string));
+ }
+
const std::string subcmd = parsed.subcmd.value_or("reuse-server");
SharedFD new_exe;
CF_EXPECT(Contains(supported_modes_, subcmd),
@@ -153,7 +162,7 @@ class CvdRestartHandler : public CvdServerHandler {
} else if (subcmd == "reuse-server") {
new_exe = CF_EXPECT(NewExecFromPath(request, kServerExecPath));
} else {
- return CF_ERR("Unrecognized command line");
+ return CF_ERR("unsupported subcommand");
}
CF_EXPECT(server_.Exec(new_exe, request.Client()));
return CF_ERR("Should be unreachable");
@@ -227,6 +236,22 @@ class CvdRestartHandler : public CvdServerHandler {
return new_exe;
}
+ Result<std::string> SerializedInstanceDatabaseToString(
+ const uid_t client_uid) {
+ auto db_json = CF_EXPECT(instance_manager_.Serialize(client_uid),
+ "Failed to serialized instance database");
+ return db_json.toStyledString();
+ }
+
+ Result<SharedFD> CreateMemFileWithSerializedDb(
+ const std::string& json_string) {
+ const std::string mem_file_name = "cvd_server_" + std::to_string(getpid());
+ auto mem_fd = SharedFD::MemfdCreateWithData(mem_file_name, json_string);
+ CF_EXPECT(mem_fd->IsOpen(),
+ "MemfdCreateWithData failed: " << mem_fd->StrError());
+ return mem_fd;
+ }
+
BuildApi& build_api_;
std::vector<std::string> supported_modes_;
FlagCollection flags_;