#s4v2 - Add functions to parse text proto directly from a file
PiperOrigin-RevId: 788085466
Change-Id: I831cb2790c37f00b3b6f03605bc933e14a530c39
diff --git a/bmc/machine_configs/setup_configs.cc b/bmc/machine_configs/setup_configs.cc
index 93514df..9f8854a 100644
--- a/bmc/machine_configs/setup_configs.cc
+++ b/bmc/machine_configs/setup_configs.cc
@@ -3,7 +3,6 @@
#include "action_context.h"
#include "bmc/machine_configs/embedded_data.h"
-#include "bmc/proto_reader.h"
#include "bmc/register_actions_bmc.h"
#include "bmc/state_monitor_bmc.h"
#include "daemon_context.h"
@@ -12,7 +11,6 @@
#include "absl/flags/flag.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
-#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "bmc/status_macros.h"
@@ -43,15 +41,6 @@
return bakedin_config;
}
-static absl::StatusOr<SafePowerAgentConfig> ReadLocalConfig(
- absl::string_view config_file_path) {
- ASSIGN_OR_RETURN(std::string config_proto_str,
- proto_reader::ReadFileToString(config_file_path));
- LOG(INFO) << "Config proto " << config_proto_str;
- return safepower_agent::ParseTextProto<SafePowerAgentConfig>(
- config_proto_str);
-}
-
// Load the configs provided
static absl::Status Load(StateMonitorBMC& state_monitor,
ActionContextManager& action_context_manager) {
@@ -71,8 +60,9 @@
absl::Status SetupConfigs(StateMonitorBMC& state_monitor,
ActionContextManager& action_context_manager,
absl::string_view local_config_path) {
- absl::StatusOr<SafePowerAgentConfig> safepower_config =
- ReadLocalConfig(local_config_path);
+ auto safepower_config =
+ safepower_agent::ParseTextProtoFromFile<SafePowerAgentConfig>(
+ std::string(local_config_path));
absl::Status load_status;
if (safepower_config.ok()) {
diff --git a/parse_text_proto.cc b/parse_text_proto.cc
index 34a97e6..f1a426e 100644
--- a/parse_text_proto.cc
+++ b/parse_text_proto.cc
@@ -1,6 +1,9 @@
#include "parse_text_proto.h"
#include <cstddef>
+#include <cstdio>
+#include <fstream>
+#include <string>
#include <vector>
#include "absl/log/log.h"
@@ -12,22 +15,37 @@
namespace safepower_agent {
namespace internal {
-static absl::string_view ExtractLine(absl::string_view text, int line) {
- std::vector<absl::string_view> lines = absl::StrSplit(text, '\n');
- return (static_cast<std::size_t>(line) < lines.size()) ? lines[line] : "";
+std::string ErrorCollectorString::ExtractLine(int line) const {
+ std::vector<absl::string_view> lines = absl::StrSplit(text_proto_, '\n');
+ return (static_cast<std::size_t>(line) < lines.size())
+ ? std::string(lines[line])
+ : "";
+}
+
+std::string ErrorCollectorFile::ExtractLine(int line) const {
+ std::ifstream file(path_);
+ std::string line_string;
+ for (int i = 0; i <= line; ++i) {
+ if (!file.good()) {
+ return "";
+ }
+ std::getline(file, line_string);
+ LOG(INFO) << "line: " << line_string;
+ }
+ return line_string;
}
void ErrorCollector::RecordError(int line, google::protobuf::io::ColumnNumber column,
absl::string_view message) {
absl::StrAppendFormat(&message_, "%s [line %d, column %d]\n%s", message,
- line + 1, column + 1, ExtractLine(text_proto_, line));
+ line + 1, column + 1, ExtractLine(line));
}
void ErrorCollector::RecordWarning(int line, google::protobuf::io::ColumnNumber column,
absl::string_view message) {
LOG(WARNING) << message << " [line " << line + 1 << ", column " << column + 1
<< "]\n"
- << ExtractLine(text_proto_, line);
+ << ExtractLine(line);
}
} // namespace internal
diff --git a/parse_text_proto.h b/parse_text_proto.h
index 3ea906e..d080718 100644
--- a/parse_text_proto.h
+++ b/parse_text_proto.h
@@ -1,22 +1,30 @@
#ifndef PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_PARSE_TEXT_PROTO_H_
#define PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_PARSE_TEXT_PROTO_H_
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstring>
+#include <optional>
#include <string>
#include <utility>
+#include <vector>
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/text_format.h"
namespace safepower_agent {
namespace internal {
class ErrorCollector : public google::protobuf::io::ErrorCollector {
public:
- explicit ErrorCollector(absl::string_view text_proto)
- : text_proto_(text_proto) {}
+ ErrorCollector() = default;
ErrorCollector(const ErrorCollector&) = delete;
ErrorCollector& operator=(const ErrorCollector&) = delete;
@@ -26,16 +34,38 @@
absl::string_view message) override;
std::string message() && { return std::move(message_); }
+ protected:
+ virtual std::string ExtractLine(int line) const = 0;
+
private:
- absl::string_view text_proto_;
std::string message_;
};
+
+class ErrorCollectorString : public ErrorCollector {
+ public:
+ explicit ErrorCollectorString(absl::string_view text_proto)
+ : text_proto_(text_proto) {}
+ std::string ExtractLine(int line) const override;
+
+ private:
+ absl::string_view text_proto_;
+};
+
+class ErrorCollectorFile : public ErrorCollector {
+ public:
+ explicit ErrorCollectorFile(const std::string& path) : path_(path) {}
+ std::string ExtractLine(int line) const override;
+
+ private:
+ const std::string& path_;
+};
+
} // namespace internal
template <typename Proto>
absl::StatusOr<Proto> ParseTextProto(absl::string_view text_proto) {
google::protobuf::TextFormat::Parser parser;
- internal::ErrorCollector error_collector(text_proto);
+ internal::ErrorCollectorString error_collector(text_proto);
parser.RecordErrorsTo(&error_collector);
Proto proto;
if (!parser.ParseFromString(text_proto, &proto)) {
@@ -43,6 +73,26 @@
}
return proto;
}
+
+template <typename Proto>
+absl::StatusOr<Proto> ParseTextProtoFromFile(const std::string& path) {
+ google::protobuf::TextFormat::Parser parser;
+ internal::ErrorCollectorFile error_collector(path);
+ parser.RecordErrorsTo(&error_collector);
+ Proto proto;
+ int fd = open(path.c_str(), O_RDONLY);
+ if (fd < 0) {
+ return absl::InvalidArgumentError(
+ absl::StrCat("Failed to open file: ", path, " :", strerror(errno)));
+ }
+ google::protobuf::io::FileInputStream stream(fd);
+ stream.SetCloseOnDelete(true);
+ if (!parser.Parse(&stream, &proto)) {
+ return absl::InvalidArgumentError(std::move(error_collector).message());
+ }
+ return proto;
+}
+
} // namespace safepower_agent
#endif // PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_PARSE_TEXT_PROTO_H_