Add ability to write log to abstract log sink
It completely decouples log writing and file system.
Change-Id: Iae3b881826e04500f4862a16c237e0f7c37c9536
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
Signed-off-by: Alexei Strots <alexei.strots@bluerivertech.com>
diff --git a/aos/events/logging/log_backend.cc b/aos/events/logging/log_backend.cc
index 2700c4d..07bb780 100644
--- a/aos/events/logging/log_backend.cc
+++ b/aos/events/logging/log_backend.cc
@@ -135,7 +135,7 @@
}
flags_ = fcntl(fd_, F_GETFL, 0);
- PCHECK(flags_ >= 0) << ": Failed to get flags for " << this->filename();
+ PCHECK(flags_ >= 0) << ": Failed to get flags for " << filename_;
EnableDirect();
@@ -151,10 +151,10 @@
// Track if we failed to set O_DIRECT. Note: Austin hasn't seen this call
// fail. The write call tends to fail instead.
if (fcntl(fd_, F_SETFL, new_flags) == -1) {
- PLOG(WARNING) << "Failed to set O_DIRECT on " << filename();
+ PLOG(WARNING) << "Failed to set O_DIRECT on " << filename_;
supports_odirect_ = false;
} else {
- VLOG(1) << "Enabled O_DIRECT on " << filename();
+ VLOG(1) << "Enabled O_DIRECT on " << filename_;
flags_ = new_flags;
}
}
@@ -164,7 +164,7 @@
if (supports_odirect_ && ODirectEnabled()) {
flags_ = flags_ & (~O_DIRECT);
PCHECK(fcntl(fd_, F_SETFL, flags_) != -1) << ": Failed to disable O_DIRECT";
- VLOG(1) << "Disabled O_DIRECT on " << filename();
+ VLOG(1) << "Disabled O_DIRECT on " << filename_;
}
}
@@ -296,7 +296,6 @@
posix_fadvise(fd_, last_synced_bytes_,
total_write_bytes_ - last_synced_bytes_,
POSIX_FADV_DONTNEED);
-
}
last_synced_bytes_ = total_write_bytes_;
}
@@ -305,7 +304,7 @@
if (aligned) {
written_aligned_ += written;
}
- write_stats_.UpdateStats(end - start, written, iovec.size());
+ WriteStatistics()->UpdateStats(end - start, written, iovec.size());
return WriteCode::kOk;
}
@@ -329,7 +328,7 @@
FileBackend::FileBackend(std::string_view base_name)
: base_name_(base_name), separator_(base_name_.back() == '/' ? "" : "_") {}
-std::unique_ptr<FileHandler> FileBackend::RequestFile(std::string_view id) {
+std::unique_ptr<LogSink> FileBackend::RequestFile(std::string_view id) {
const std::string filename = absl::StrCat(base_name_, separator_, id);
return std::make_unique<FileHandler>(filename);
}
@@ -337,7 +336,7 @@
RenamableFileBackend::RenamableFileBackend(std::string_view base_name)
: base_name_(base_name), separator_(base_name_.back() == '/' ? "" : "_") {}
-std::unique_ptr<FileHandler> RenamableFileBackend::RequestFile(
+std::unique_ptr<LogSink> RenamableFileBackend::RequestFile(
std::string_view id) {
const std::string filename =
absl::StrCat(base_name_, separator_, id, temp_suffix_);
diff --git a/aos/events/logging/log_backend.h b/aos/events/logging/log_backend.h
index b3cea6c..1b1417e 100644
--- a/aos/events/logging/log_backend.h
+++ b/aos/events/logging/log_backend.h
@@ -77,7 +77,42 @@
size_t messages_written = 0;
};
-// Source for iovec with additional flag that pointer and size of data is
+// Interface that abstract writing to log from media.
+class LogSink {
+ public:
+ LogSink() = default;
+ virtual ~LogSink() = default;
+
+ LogSink(const LogSink &) = delete;
+ LogSink &operator=(const LogSink &) = delete;
+
+ // Try to open file. App will crash if there are other than out-of-space
+ // problems with backend media.
+ virtual WriteCode OpenForWrite() = 0;
+
+ // Close the file handler.
+ virtual WriteCode Close() = 0;
+
+ // Returns true if sink is open and need to be closed.
+ virtual bool is_open() const = 0;
+
+ // Peeks messages from queue and writes it to file. Returns code when
+ // out-of-space problem occurred along with number of messages from queue that
+ // was written.
+ virtual WriteResult Write(
+ const absl::Span<const absl::Span<const uint8_t>> &queue) = 0;
+
+ // Get access to statistics related to the write operations.
+ WriteStats *WriteStatistics() { return &write_stats_; }
+
+ // Name of the log sink.
+ virtual std::string_view name() const = 0;
+
+ private:
+ WriteStats write_stats_;
+};
+
+// Source for iovec with an additional flag that pointer and size of data is
// aligned and be ready for O_DIRECT operation.
struct AlignedIovec {
const uint8_t *data;
@@ -124,28 +159,28 @@
// 4) Not all filesystems support O_DIRECT, and different sizes may be optimal
// for different machines. The defaults should work decently anywhere and
// be tunable for faster systems.
-class FileHandler {
+class FileHandler : public LogSink {
public:
// Size of an aligned sector used to detect when the data is aligned enough to
// use O_DIRECT instead.
static constexpr size_t kSector = 512u;
explicit FileHandler(std::string filename);
- virtual ~FileHandler();
+ ~FileHandler() override;
FileHandler(const FileHandler &) = delete;
FileHandler &operator=(const FileHandler &) = delete;
// Try to open file. App will crash if there are other than out-of-space
// problems with backend media.
- virtual WriteCode OpenForWrite();
+ WriteCode OpenForWrite() override;
// Close the file handler.
- virtual WriteCode Close();
+ WriteCode Close() override;
// This will be true until Close() is called, unless the file couldn't be
// created due to running out of space.
- bool is_open() const { return fd_ != -1; }
+ bool is_open() const override { return fd_ != -1; }
// Peeks messages from queue and writes it to file. Returns code when
// out-of-space problem occurred along with number of messages from queue that
@@ -155,21 +190,19 @@
// write faster if the spans passed in start at aligned addresses, and are
// multiples of kSector long (and the data written so far is also a multiple
// of kSector length).
- virtual WriteResult Write(
- const absl::Span<const absl::Span<const uint8_t>> &queue);
+ WriteResult Write(
+ const absl::Span<const absl::Span<const uint8_t>> &queue) override;
- // TODO (Alexei): it is rather leaked abstraction.
- // Path to the concrete log file.
- std::string_view filename() const { return filename_; }
-
- int fd() const { return fd_; }
-
- // Get access to statistics related to the write operations.
- WriteStats *WriteStatistics() { return &write_stats_; }
+ // Name of the log sink mostly for informational purposes.
+ std::string_view name() const override { return filename_; }
// Number of bytes written in aligned mode. It is mostly for testing.
size_t written_aligned() const { return written_aligned_; }
+ protected:
+ // This is used by subclasses who need to access filename.
+ std::string_view filename() const { return filename_; }
+
private:
// Enables O_DIRECT on the open file if it is supported. Cheap to call if it
// is already enabled.
@@ -201,8 +234,6 @@
bool supports_odirect_ = true;
int flags_ = 0;
-
- WriteStats write_stats_;
};
// Class that decouples log writing and media (file system or memory). It is
@@ -214,7 +245,7 @@
// Request file-like object from the log backend. It maybe a file on a disk or
// in memory. id is usually generated by log namer and looks like name of the
// file within a log folder.
- virtual std::unique_ptr<FileHandler> RequestFile(std::string_view id) = 0;
+ virtual std::unique_ptr<LogSink> RequestFile(std::string_view id) = 0;
};
// Implements requests log files from file system.
@@ -225,7 +256,7 @@
~FileBackend() override = default;
// Request file from a file system. It is not open yet.
- std::unique_ptr<FileHandler> RequestFile(std::string_view id) override;
+ std::unique_ptr<LogSink> RequestFile(std::string_view id) override;
private:
const std::string base_name_;
@@ -254,7 +285,7 @@
~RenamableFileBackend() = default;
// Request file from a file system. It is not open yet.
- std::unique_ptr<FileHandler> RequestFile(std::string_view id) override;
+ std::unique_ptr<LogSink> RequestFile(std::string_view id) override;
// TODO (Alexei): it is called by Logger, and left here for compatibility.
// Logger should not call it.
diff --git a/aos/events/logging/log_backend_test.cc b/aos/events/logging/log_backend_test.cc
index b969218..928bb24 100644
--- a/aos/events/logging/log_backend_test.cc
+++ b/aos/events/logging/log_backend_test.cc
@@ -14,13 +14,24 @@
#include "gtest/gtest.h"
namespace aos::logger::testing {
+namespace {
+// Helper to write simple string to the log sink
+WriteResult Write(LogSink *log_sink, std::string_view content) {
+ auto span = absl::Span<const uint8_t>(
+ reinterpret_cast<const unsigned char *>(content.data()), content.size());
+ auto queue = absl::Span<const absl::Span<const uint8_t>>(&span, 1);
+ return log_sink->Write(queue);
+}
+} // namespace
+
TEST(LogBackendTest, CreateSimpleFile) {
const std::string logevent = aos::testing::TestTmpDir() + "/logevent/";
FileBackend backend(logevent);
auto file = backend.RequestFile("test.log");
ASSERT_EQ(file->OpenForWrite(), WriteCode::kOk);
- auto result = write(file->fd(), "test", 4);
- EXPECT_GT(result, 0);
+ auto result = Write(file.get(), "test");
+ EXPECT_EQ(result.code, WriteCode::kOk);
+ EXPECT_EQ(result.messages_written, 1);
EXPECT_EQ(file->Close(), WriteCode::kOk);
EXPECT_TRUE(std::filesystem::exists(logevent + "test.log"));
}
@@ -30,8 +41,9 @@
RenamableFileBackend backend(logevent);
auto file = backend.RequestFile("test.log");
ASSERT_EQ(file->OpenForWrite(), WriteCode::kOk);
- auto result = write(file->fd(), "testtest", 8);
- EXPECT_GT(result, 0);
+ auto result = Write(file.get(), "test");
+ EXPECT_EQ(result.code, WriteCode::kOk);
+ EXPECT_EQ(result.messages_written, 1);
EXPECT_EQ(file->Close(), WriteCode::kOk);
EXPECT_TRUE(std::filesystem::exists(logevent + "test.log"));
}
@@ -42,8 +54,9 @@
backend.EnableTempFiles();
auto file = backend.RequestFile("test.log");
ASSERT_EQ(file->OpenForWrite(), WriteCode::kOk);
- auto result = write(file->fd(), "testtest", 8);
- EXPECT_GT(result, 0);
+ auto result = Write(file.get(), "test");
+ EXPECT_EQ(result.code, WriteCode::kOk);
+ EXPECT_EQ(result.messages_written, 1);
EXPECT_TRUE(std::filesystem::exists(logevent + "test.log.tmp"));
EXPECT_EQ(file->Close(), WriteCode::kOk);
@@ -56,8 +69,9 @@
RenamableFileBackend backend(logevent);
auto file = backend.RequestFile("test.log");
ASSERT_EQ(file->OpenForWrite(), WriteCode::kOk);
- auto result = write(file->fd(), "testtest", 8);
- EXPECT_GT(result, 0);
+ auto result = Write(file.get(), "test");
+ EXPECT_EQ(result.code, WriteCode::kOk);
+ EXPECT_EQ(result.messages_written, 1);
EXPECT_TRUE(std::filesystem::exists(logevent + "test.log"));
std::string renamed = aos::testing::TestTmpDir() + "/renamed/";
@@ -77,8 +91,9 @@
backend.EnableTempFiles();
auto file = backend.RequestFile("test.log");
ASSERT_EQ(file->OpenForWrite(), WriteCode::kOk);
- auto result = write(file->fd(), "testtest", 8);
- EXPECT_GT(result, 0);
+ auto result = Write(file.get(), "test");
+ EXPECT_EQ(result.code, WriteCode::kOk);
+ EXPECT_EQ(result.messages_written, 1);
EXPECT_TRUE(std::filesystem::exists(logevent + "test.log.tmp"));
std::string renamed = aos::testing::TestTmpDir() + "/renamed/";
@@ -364,7 +379,8 @@
auto result = handler->Write(queue);
EXPECT_EQ(result.code, WriteCode::kOk);
EXPECT_EQ(result.messages_written, queue.size());
- EXPECT_GT(handler->written_aligned(), 0);
+ FileHandler *file_handler = reinterpret_cast<FileHandler *>(handler.get());
+ EXPECT_GT(file_handler->written_aligned(), 0);
ASSERT_EQ(handler->Close(), WriteCode::kOk);
EXPECT_TRUE(std::filesystem::exists(file));
diff --git a/aos/events/logging/log_namer.cc b/aos/events/logging/log_namer.cc
index 10e08db..4b23268 100644
--- a/aos/events/logging/log_namer.cc
+++ b/aos/events/logging/log_namer.cc
@@ -45,7 +45,7 @@
void NewDataWriter::Rotate() {
// No need to rotate if nothing has been written.
if (header_written_) {
- VLOG(1) << "Rotated " << filename();
+ VLOG(1) << "Rotated " << name();
++parts_index_;
reopen_(this);
header_written_ = false;
@@ -77,7 +77,7 @@
state_[node_index_].boot_uuid = source_node_boot_uuid;
- VLOG(1) << "Rebooted " << filename();
+ VLOG(1) << "Rebooted " << name();
}
void NewDataWriter::UpdateBoot(const UUID &source_node_boot_uuid) {
@@ -101,7 +101,7 @@
// Did the remote boot UUID change?
if (state.boot_uuid != remote_node_boot_uuid) {
- VLOG(1) << filename() << " Remote " << remote_node_index << " updated to "
+ VLOG(1) << name() << " Remote " << remote_node_index << " updated to "
<< remote_node_boot_uuid << " from " << state.boot_uuid;
state.boot_uuid = remote_node_boot_uuid;
state.oldest_remote_monotonic_timestamp = monotonic_clock::max_time;
@@ -124,7 +124,7 @@
if (!reliable) {
if (state.oldest_remote_unreliable_monotonic_timestamp >
monotonic_remote_time) {
- VLOG(1) << filename() << " Remote " << remote_node_index
+ VLOG(1) << name() << " Remote " << remote_node_index
<< " oldest_remote_unreliable_monotonic_timestamp updated from "
<< state.oldest_remote_unreliable_monotonic_timestamp << " to "
<< monotonic_remote_time;
@@ -136,7 +136,7 @@
} else {
if (state.oldest_remote_reliable_monotonic_timestamp >
monotonic_remote_time) {
- VLOG(1) << filename() << " Remote " << remote_node_index
+ VLOG(1) << name() << " Remote " << remote_node_index
<< " oldest_remote_reliable_monotonic_timestamp updated from "
<< state.oldest_remote_reliable_monotonic_timestamp << " to "
<< monotonic_remote_time;
@@ -153,7 +153,7 @@
if (monotonic_event_time <
logger_state.oldest_logger_remote_unreliable_monotonic_timestamp) {
VLOG(1)
- << filename() << " Remote " << node_index_
+ << name() << " Remote " << node_index_
<< " oldest_logger_remote_unreliable_monotonic_timestamp updated "
"from "
<< logger_state.oldest_logger_remote_unreliable_monotonic_timestamp
@@ -169,7 +169,7 @@
// Did any of the timestamps change?
if (state.oldest_remote_monotonic_timestamp > monotonic_remote_time) {
- VLOG(1) << filename() << " Remote " << remote_node_index
+ VLOG(1) << name() << " Remote " << remote_node_index
<< " oldest_remote_monotonic_timestamp updated from "
<< state.oldest_remote_monotonic_timestamp << " to "
<< monotonic_remote_time;
@@ -205,7 +205,7 @@
CHECK_EQ(state_[node_index_].boot_uuid, source_node_boot_uuid);
CHECK(writer);
CHECK(header_written_) << ": Attempting to write message before header to "
- << writer->filename();
+ << writer->name();
writer->CopyMessage(coppier, now);
}
@@ -214,7 +214,7 @@
const size_t logger_node_index = log_namer_->logger_node_index();
const UUID &logger_node_boot_uuid = log_namer_->logger_node_boot_uuid();
if (state_[logger_node_index].boot_uuid == UUID::Zero()) {
- VLOG(1) << filename() << " Logger node is " << logger_node_index
+ VLOG(1) << name() << " Logger node is " << logger_node_index
<< " and uuid is " << logger_node_boot_uuid;
state_[logger_node_index].boot_uuid = logger_node_boot_uuid;
} else {
@@ -227,7 +227,7 @@
void NewDataWriter::QueueHeader(
aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> &&header) {
CHECK(!header_written_) << ": Attempting to write duplicate header to "
- << writer->filename();
+ << writer->name();
CHECK(header.message().has_source_node_boot_uuid());
CHECK_EQ(state_[node_index_].boot_uuid,
UUID::FromString(header.message().source_node_boot_uuid()));
@@ -245,7 +245,7 @@
reopen_(this);
}
- VLOG(1) << "Writing to " << filename() << " "
+ VLOG(1) << "Writing to " << name() << " "
<< aos::FlatbufferToJson(
header, {.multi_line = false, .max_vector_size = 100});
@@ -560,14 +560,14 @@
return result;
}
-MultiNodeLogNamer::MultiNodeLogNamer(
- std::unique_ptr<LogBackend> log_backend, EventLoop *event_loop)
+MultiNodeLogNamer::MultiNodeLogNamer(std::unique_ptr<LogBackend> log_backend,
+ EventLoop *event_loop)
: MultiNodeLogNamer(std::move(log_backend), event_loop->configuration(),
event_loop, event_loop->node()) {}
-MultiNodeLogNamer::MultiNodeLogNamer(
- std::unique_ptr<LogBackend> log_backend,
- const Configuration *configuration, EventLoop *event_loop, const Node *node)
+MultiNodeLogNamer::MultiNodeLogNamer(std::unique_ptr<LogBackend> log_backend,
+ const Configuration *configuration,
+ EventLoop *event_loop, const Node *node)
: LogNamer(configuration, event_loop, node),
log_backend_(std::move(log_backend)),
encoder_factory_([](size_t max_message_size) {
@@ -826,7 +826,6 @@
return;
}
DetachedBufferWriter *const writer = writer_pointer->get();
- const bool was_open = writer->is_open();
writer->Close();
const auto *stats = writer->WriteStatistics();
@@ -844,11 +843,6 @@
ran_out_of_space_ = true;
writer->acknowledge_out_of_space();
}
-
- if (!was_open) {
- CHECK(access(std::string(writer->filename()).c_str(), F_OK) == -1)
- << ": File should not exist: " << writer->filename();
- }
}
} // namespace logger
diff --git a/aos/events/logging/log_namer.h b/aos/events/logging/log_namer.h
index fcb3f87..8842f4e 100644
--- a/aos/events/logging/log_namer.h
+++ b/aos/events/logging/log_namer.h
@@ -43,7 +43,8 @@
void UpdateMaxMessageSize(size_t new_size) {
if (new_size > max_message_size_) {
- CHECK(!header_written_);
+ CHECK(!header_written_) << ": Tried to update to " << new_size << ", was "
+ << max_message_size_ << " for " << name();
max_message_size_ = new_size;
}
}
@@ -77,10 +78,8 @@
// update the remote timestamps.
void UpdateBoot(const UUID &source_node_boot_uuid);
- // Returns the filename of the writer.
- std::string_view filename() const {
- return writer ? writer->filename() : "(closed)";
- }
+ // Returns the name of the writer. It may be a filename, but assume it is not.
+ std::string_view name() const { return writer ? writer->name() : "(closed)"; }
void Close();
diff --git a/aos/events/logging/log_writer.cc b/aos/events/logging/log_writer.cc
index b6ee4a5..d559311 100644
--- a/aos/events/logging/log_writer.cc
+++ b/aos/events/logging/log_writer.cc
@@ -230,8 +230,6 @@
}
}
-
-
std::string Logger::WriteConfiguration(LogNamer *log_namer) {
std::string config_sha256;
@@ -348,8 +346,7 @@
// Make sure we read up until "now" and log it. This sets us up so that we
// are unlikely to fetch a message far in the future and have a ton of data
// before the offical start time.
- monotonic_clock::time_point newest_record =
- monotonic_clock::min_time;
+ monotonic_clock::time_point newest_record = monotonic_clock::min_time;
while (true) {
aos::monotonic_clock::time_point next_time =
last_synchronized_time_ + polling_period_;
@@ -737,7 +734,7 @@
VLOG(2) << "Wrote data as node " << FlatbufferToJson(node_)
<< " for channel "
<< configuration::CleanedChannelToString(f.fetcher->channel())
- << " to " << writer->filename();
+ << " to " << writer->name();
}
}
@@ -762,7 +759,7 @@
VLOG(2) << "Wrote timestamps as node " << FlatbufferToJson(node_)
<< " for channel "
<< configuration::CleanedChannelToString(f.fetcher->channel())
- << " to " << timestamp_writer->filename() << " timestamp";
+ << " to " << timestamp_writer->name() << " timestamp";
}
}
diff --git a/aos/events/logging/logfile_utils.cc b/aos/events/logging/logfile_utils.cc
index 27c6c3b..490393d 100644
--- a/aos/events/logging/logfile_utils.cc
+++ b/aos/events/logging/logfile_utils.cc
@@ -80,12 +80,11 @@
}
} // namespace
-DetachedBufferWriter::DetachedBufferWriter(
- std::unique_ptr<FileHandler> file_handler,
- std::unique_ptr<DataEncoder> encoder)
- : file_handler_(std::move(file_handler)), encoder_(std::move(encoder)) {
- CHECK(file_handler_);
- ran_out_of_space_ = file_handler_->OpenForWrite() == WriteCode::kOutOfSpace;
+DetachedBufferWriter::DetachedBufferWriter(std::unique_ptr<LogSink> log_sink,
+ std::unique_ptr<DataEncoder> encoder)
+ : log_sink_(std::move(log_sink)), encoder_(std::move(encoder)) {
+ CHECK(log_sink_);
+ ran_out_of_space_ = log_sink_->OpenForWrite() == WriteCode::kOutOfSpace;
if (ran_out_of_space_) {
LOG(WARNING) << "And we are out of space";
}
@@ -108,7 +107,7 @@
// (because that data will then be its data).
DetachedBufferWriter &DetachedBufferWriter::operator=(
DetachedBufferWriter &&other) {
- std::swap(file_handler_, other.file_handler_);
+ std::swap(log_sink_, other.log_sink_);
std::swap(encoder_, other.encoder_);
std::swap(ran_out_of_space_, other.ran_out_of_space_);
std::swap(acknowledge_ran_out_of_space_, other.acknowledge_ran_out_of_space_);
@@ -147,7 +146,7 @@
}
void DetachedBufferWriter::Close() {
- if (!file_handler_->is_open()) {
+ if (!log_sink_->is_open()) {
return;
}
encoder_->Finish();
@@ -155,7 +154,7 @@
Flush(monotonic_clock::max_time);
}
encoder_.reset();
- ran_out_of_space_ = file_handler_->Close() == WriteCode::kOutOfSpace;
+ ran_out_of_space_ = log_sink_->Close() == WriteCode::kOutOfSpace;
}
void DetachedBufferWriter::Flush(aos::monotonic_clock::time_point now) {
@@ -178,7 +177,7 @@
return;
}
- const WriteResult result = file_handler_->Write(queue);
+ const WriteResult result = log_sink_->Write(queue);
encoder_->Clear(result.messages_written);
ran_out_of_space_ = result.code == WriteCode::kOutOfSpace;
}
diff --git a/aos/events/logging/logfile_utils.h b/aos/events/logging/logfile_utils.h
index c75c8fb..8415efe 100644
--- a/aos/events/logging/logfile_utils.h
+++ b/aos/events/logging/logfile_utils.h
@@ -51,7 +51,7 @@
// Marker struct for one of our constructor overloads.
struct already_out_of_space_t {};
- DetachedBufferWriter(std::unique_ptr<FileHandler> file_handler,
+ DetachedBufferWriter(std::unique_ptr<LogSink> log_sink,
std::unique_ptr<DataEncoder> encoder);
// Creates a dummy instance which won't even open a file. It will act as if
// opening the file ran out of space immediately.
@@ -64,11 +64,11 @@
DetachedBufferWriter &operator=(DetachedBufferWriter &&other);
DetachedBufferWriter &operator=(const DetachedBufferWriter &) = delete;
- std::string_view filename() const { return file_handler_->filename(); }
+ std::string_view name() const { return log_sink_->name(); }
// This will be true until Close() is called, unless the file couldn't be
// created due to running out of space.
- bool is_open() const { return file_handler_->is_open(); }
+ bool is_open() const { return log_sink_->is_open(); }
// Queues up a finished FlatBufferBuilder to be encoded and written.
//
@@ -106,7 +106,7 @@
return encoder_->total_bytes();
}
- WriteStats* WriteStatistics() const { return file_handler_->WriteStatistics(); }
+ WriteStats *WriteStatistics() const { return log_sink_->WriteStatistics(); }
private:
// Performs a single writev call with as much of the data we have queued up as
@@ -124,7 +124,7 @@
// the current time. It just needs to be close.
void FlushAtThreshold(aos::monotonic_clock::time_point now);
- std::unique_ptr<FileHandler> file_handler_;
+ std::unique_ptr<LogSink> log_sink_;
std::unique_ptr<DataEncoder> encoder_;
bool ran_out_of_space_ = false;