Split configuration into a separate file.

This saves space and CPU.  The configuration can't change (by design) in
a log file, so it was previously being duplicated.  In some cases with
lots of forwarded messages and nodes, rotating was triggering
recompression of enough configuration information that we were falling
behind.

Note: on purpose, we aren't storing a link from the log file to the
header.  We don't store links between parts either.  It up to the user
to provide the config in the list of files and folders provided.

Change-Id: I2cd600ed76c5f6f4b2bd6ba77d49bc739227756f
diff --git a/aos/events/logging/log_namer.cc b/aos/events/logging/log_namer.cc
index 2d1e111..44e8f5a 100644
--- a/aos/events/logging/log_namer.cc
+++ b/aos/events/logging/log_namer.cc
@@ -50,6 +50,18 @@
   UpdateHeader(header, uuid_, part_number_);
   data_writer_->QueueSpan(header->span());
 }
+
+void LocalLogNamer::WriteConfiguration(
+    aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
+    std::string_view config_sha256) {
+  const std::string filename = absl::StrCat(base_name_, config_sha256, ".bfbs");
+
+  std::unique_ptr<DetachedBufferWriter> writer =
+      std::make_unique<DetachedBufferWriter>(
+          filename, std::make_unique<aos::logger::DummyEncoder>());
+  writer->QueueSizedFlatbuffer(header->Release());
+}
+
 void LocalLogNamer::Reboot(
     const Node * /*node*/,
     aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> * /*header*/) {
@@ -120,7 +132,8 @@
 
 void MultiNodeLogNamer::DoRotate(
     const Node *node,
-    aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header, bool reboot) {
+    aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
+    bool reboot) {
   if (node == this->node()) {
     if (data_writer_.writer) {
       if (reboot) {
@@ -148,6 +161,28 @@
   }
 }
 
+void MultiNodeLogNamer::WriteConfiguration(
+    aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
+    std::string_view config_sha256) {
+  if (ran_out_of_space_) {
+    return;
+  }
+
+  const std::string_view separator = base_name_.back() == '/' ? "" : "_";
+  const std::string filename = absl::StrCat(
+      base_name_, separator, config_sha256, ".bfbs", extension_, temp_suffix_);
+
+  std::unique_ptr<DetachedBufferWriter> writer =
+      std::make_unique<DetachedBufferWriter>(filename, encoder_factory_());
+
+  writer->QueueSizedFlatbuffer(header->Release());
+
+  if (!writer->ran_out_of_space()) {
+    all_filenames_.emplace_back(filename);
+  }
+  CloseWriter(&writer);
+}
+
 DetachedBufferWriter *MultiNodeLogNamer::MakeWriter(const Channel *channel) {
   // See if we can read the data on this node at all.
   const bool is_readable =