blob: f1f1829efd6a7642fff81818618ccfd6fda637d8 [file] [log] [blame]
Austin Schuhcb5601b2020-09-10 15:29:59 -07001#ifndef AOS_EVENTS_LOGGING_LOG_NAMER_H_
2#define AOS_EVENTS_LOGGING_LOG_NAMER_H_
3
4#include <functional>
5#include <map>
6#include <memory>
7#include <string_view>
8#include <vector>
9
Austin Schuh58646e22021-08-23 23:51:46 -070010#include "absl/container/btree_map.h"
Austin Schuhcb5601b2020-09-10 15:29:59 -070011#include "aos/events/logging/logfile_utils.h"
12#include "aos/events/logging/logger_generated.h"
Austin Schuh4385b142021-03-14 21:31:13 -070013#include "aos/uuid.h"
Austin Schuhcb5601b2020-09-10 15:29:59 -070014#include "flatbuffers/flatbuffers.h"
15
16namespace aos {
17namespace logger {
18
Austin Schuh572924a2021-07-30 22:32:12 -070019class LogNamer;
20
Austin Schuhb8bca732021-07-30 22:32:00 -070021// TODO(austin): Rename this back to DataWriter once all other callers are of
22// the old DataWriter.
Austin Schuh572924a2021-07-30 22:32:12 -070023//
24// Class to manage writing data to log files. This lets us track which boot the
25// written header has in it, and if the header has been written or not.
Austin Schuh58646e22021-08-23 23:51:46 -070026//
27// The design of this class is that instead of being notified when any of the
28// header data changes, it polls and owns that decision. This makes it much
29// harder to write corrupted data. If that becomes a performance problem, we
30// can DCHECK and take it out of production binaries.
Austin Schuhb8bca732021-07-30 22:32:00 -070031class NewDataWriter {
32 public:
33 // Constructs a NewDataWriter.
Austin Schuh572924a2021-07-30 22:32:12 -070034 // log_namer is the log namer which holds the config and any other data we
35 // need for our header.
36 // node is the node whom's prespective we are logging from.
Austin Schuhb8bca732021-07-30 22:32:00 -070037 // reopen is called whenever a file needs to be reopened.
38 // close is called to close that file and extract any statistics.
Austin Schuh572924a2021-07-30 22:32:12 -070039 NewDataWriter(LogNamer *log_namer, const Node *node,
40 std::function<void(NewDataWriter *)> reopen,
41 std::function<void(NewDataWriter *)> close);
Austin Schuhb8bca732021-07-30 22:32:00 -070042
43 NewDataWriter(NewDataWriter &&other) = default;
44 aos::logger::NewDataWriter &operator=(NewDataWriter &&other) = default;
45 NewDataWriter(const NewDataWriter &) = delete;
46 void operator=(const NewDataWriter &) = delete;
47
Austin Schuh572924a2021-07-30 22:32:12 -070048 ~NewDataWriter();
Austin Schuhb8bca732021-07-30 22:32:00 -070049
Austin Schuh572924a2021-07-30 22:32:12 -070050 // Rotates the log file, delaying writing the new header until data arrives.
51 void Rotate();
Austin Schuhb8bca732021-07-30 22:32:00 -070052
Austin Schuh72211ae2021-08-05 14:02:30 -070053 void UpdateRemote(size_t remote_node_index, const UUID &remote_node_boot_uuid,
54 monotonic_clock::time_point monotonic_remote_time,
55 monotonic_clock::time_point monotonic_event_time,
56 bool reliable);
Austin Schuh572924a2021-07-30 22:32:12 -070057 // Queues up a message with the provided boot UUID.
Austin Schuhe46492f2021-07-31 19:49:41 -070058 void QueueMessage(flatbuffers::FlatBufferBuilder *fbb,
59 const UUID &node_boot_uuid,
60 aos::monotonic_clock::time_point now);
Austin Schuhb8bca732021-07-30 22:32:00 -070061
Austin Schuh572924a2021-07-30 22:32:12 -070062 // Returns the filename of the writer.
Austin Schuh58646e22021-08-23 23:51:46 -070063 std::string_view filename() const {
64 return writer ? writer->filename() : "(closed)";
65 }
Austin Schuhb8bca732021-07-30 22:32:00 -070066
Austin Schuh572924a2021-07-30 22:32:12 -070067 void Close();
Austin Schuhb8bca732021-07-30 22:32:00 -070068
69 std::unique_ptr<DetachedBufferWriter> writer = nullptr;
Austin Schuh572924a2021-07-30 22:32:12 -070070
71 size_t node_index() const { return node_index_; }
72 const UUID &parts_uuid() const { return parts_uuid_; }
73 size_t parts_index() const { return parts_index_; }
74 const Node *node() const { return node_; }
Austin Schuhb8bca732021-07-30 22:32:00 -070075
Austin Schuh72211ae2021-08-05 14:02:30 -070076 // Datastructure used to capture all the information about a remote node.
77 struct State {
78 // Boot UUID of the node.
79 UUID boot_uuid = UUID::Zero();
80 // Timestamp on the remote monotonic clock of the oldest message sent to
81 // node_index_.
82 monotonic_clock::time_point oldest_remote_monotonic_timestamp =
83 monotonic_clock::max_time;
84 // Timestamp on the local monotonic clock of the message in
85 // oldest_remote_monotonic_timestamp.
86 monotonic_clock::time_point oldest_local_monotonic_timestamp =
87 monotonic_clock::max_time;
88 // Timestamp on the remote monotonic clock of the oldest message sent to
89 // node_index_, excluding messages forwarded with time_to_live() == 0.
90 monotonic_clock::time_point oldest_remote_unreliable_monotonic_timestamp =
91 monotonic_clock::max_time;
92 // Timestamp on the local monotonic clock of the message in
93 // oldest_local_unreliable_monotonic_timestamp.
94 monotonic_clock::time_point oldest_local_unreliable_monotonic_timestamp =
95 monotonic_clock::max_time;
96 };
97
Austin Schuhb8bca732021-07-30 22:32:00 -070098 private:
Austin Schuhe46492f2021-07-31 19:49:41 -070099 // Signals that a node has rebooted.
100 void Reboot();
101
Austin Schuh572924a2021-07-30 22:32:12 -0700102 void QueueHeader(
103 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> &&header);
104
Austin Schuhe46492f2021-07-31 19:49:41 -0700105 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> MakeHeader();
106
Austin Schuh58646e22021-08-23 23:51:46 -0700107 monotonic_clock::time_point monotonic_start_time_ = monotonic_clock::min_time;
108
Austin Schuh572924a2021-07-30 22:32:12 -0700109 const Node *const node_ = nullptr;
Austin Schuhe46492f2021-07-31 19:49:41 -0700110 const size_t node_index_ = 0;
Austin Schuh572924a2021-07-30 22:32:12 -0700111 LogNamer *log_namer_;
112 UUID parts_uuid_ = UUID::Random();
113 size_t parts_index_ = 0;
114
Austin Schuhb8bca732021-07-30 22:32:00 -0700115 std::function<void(NewDataWriter *)> reopen_;
116 std::function<void(NewDataWriter *)> close_;
Austin Schuh572924a2021-07-30 22:32:12 -0700117 bool header_written_ = false;
Austin Schuhe46492f2021-07-31 19:49:41 -0700118
Austin Schuh72211ae2021-08-05 14:02:30 -0700119 std::vector<State> state_;
Austin Schuhb8bca732021-07-30 22:32:00 -0700120};
121
Austin Schuhcb5601b2020-09-10 15:29:59 -0700122// Interface describing how to name, track, and add headers to log file parts.
123class LogNamer {
124 public:
125 // Constructs a LogNamer with the primary node (ie the one the logger runs on)
126 // being node.
Austin Schuh5b728b72021-06-16 14:57:15 -0700127 LogNamer(const aos::Configuration *configuration, EventLoop *event_loop,
128 const aos::Node *node)
Austin Schuha499cea2021-07-31 19:49:53 -0700129 : event_loop_(event_loop),
Austin Schuh5b728b72021-06-16 14:57:15 -0700130 configuration_(configuration),
131 node_(node),
Austin Schuha499cea2021-07-31 19:49:53 -0700132 logger_node_index_(configuration::GetNodeIndex(configuration_, node_)) {
Austin Schuh73340842021-07-30 22:32:06 -0700133 nodes_.emplace_back(node_);
Austin Schuh73340842021-07-30 22:32:06 -0700134 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700135 virtual ~LogNamer() {}
136
Austin Schuh6bb8a822021-03-31 23:04:39 -0700137 virtual std::string_view base_name() const = 0;
138
139 // Rotate should be called at least once in between calls to set_base_name.
140 // Otherwise temporary files will not be recoverable.
141 // Rotate is called by Logger::RenameLogBase, which is currently the only user
142 // of this method.
143 // Only renaming the folder is supported, not the file base name.
144 virtual void set_base_name(std::string_view base_name) = 0;
145
Brian Silverman87ac0402020-09-17 14:47:01 -0700146 // Returns a writer for writing data from messages on this channel (on the
147 // primary node).
148 //
149 // The returned pointer will stay valid across rotations, but the object it
150 // points to will be assigned to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700151 virtual NewDataWriter *MakeWriter(const Channel *channel) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700152
Brian Silverman87ac0402020-09-17 14:47:01 -0700153 // Returns a writer for writing timestamps from messages on this channel (on
154 // the primary node).
155 //
156 // The returned pointer will stay valid across rotations, but the object it
157 // points to will be assigned to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700158 virtual NewDataWriter *MakeTimestampWriter(const Channel *channel) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700159
160 // Returns a writer for writing timestamps delivered over the special
161 // /aos/remote_timestamps/* channels. node is the node that the timestamps
Brian Silverman87ac0402020-09-17 14:47:01 -0700162 // are forwarded back from (to the primary node).
163 //
164 // The returned pointer will stay valid across rotations, but the object it
165 // points to will be assigned to.
Austin Schuh73340842021-07-30 22:32:06 -0700166 virtual NewDataWriter *MakeForwardedTimestampWriter(const Channel *channel,
167 const Node *node) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700168
Austin Schuh73340842021-07-30 22:32:06 -0700169 // Rotates all log files for the provided node.
170 virtual void Rotate(const Node *node) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700171
172 // Returns all the nodes that data is being written for.
173 const std::vector<const Node *> &nodes() const { return nodes_; }
174
175 // Returns the node the logger is running on.
176 const Node *node() const { return node_; }
Austin Schuhe46492f2021-07-31 19:49:41 -0700177 const UUID &logger_node_boot_uuid() const { return logger_node_boot_uuid_; }
178 size_t logger_node_index() const { return logger_node_index_; }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700179
Austin Schuh8c399962020-12-25 21:51:45 -0800180 // Writes out the nested Configuration object to the config file location.
181 virtual void WriteConfiguration(
182 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
183 std::string_view config_sha256) = 0;
184
Austin Schuh73340842021-07-30 22:32:06 -0700185 void SetHeaderTemplate(
186 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> header) {
187 header_ = std::move(header);
Austin Schuhe46492f2021-07-31 19:49:41 -0700188 logger_node_boot_uuid_ =
189 UUID::FromString(header_.message().logger_node_boot_uuid());
Austin Schuh73340842021-07-30 22:32:06 -0700190 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700191
Austin Schuh58646e22021-08-23 23:51:46 -0700192 void ClearStartTimes() {
193 node_states_.clear();
194 }
195
196 void SetStartTimes(size_t node_index, const UUID &boot_uuid,
Austin Schuh73340842021-07-30 22:32:06 -0700197 monotonic_clock::time_point monotonic_start_time,
198 realtime_clock::time_point realtime_start_time,
199 monotonic_clock::time_point logger_monotonic_start_time,
200 realtime_clock::time_point logger_realtime_start_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700201 VLOG(1) << "Setting node " << node_index << " to start time "
202 << monotonic_start_time << " rt " << realtime_start_time << " UUID "
203 << boot_uuid;
204 NodeState *node_state = GetNodeState(node_index, boot_uuid);
205 node_state->monotonic_start_time = monotonic_start_time;
206 node_state->realtime_start_time = realtime_start_time;
207 node_state->logger_monotonic_start_time = logger_monotonic_start_time;
208 node_state->logger_realtime_start_time = logger_realtime_start_time;
Austin Schuh73340842021-07-30 22:32:06 -0700209 }
210
Austin Schuh58646e22021-08-23 23:51:46 -0700211 monotonic_clock::time_point monotonic_start_time(size_t node_index,
212 const UUID &boot_uuid) {
213 DCHECK_NE(boot_uuid, UUID::Zero());
214
215 NodeState *node_state = GetNodeState(node_index, boot_uuid);
216 return node_state->monotonic_start_time;
Austin Schuh73340842021-07-30 22:32:06 -0700217 }
218
Austin Schuh73340842021-07-30 22:32:06 -0700219 protected:
Austin Schuh73340842021-07-30 22:32:06 -0700220 // Structure with state per node about times and such.
Austin Schuh73340842021-07-30 22:32:06 -0700221 struct NodeState {
222 // Time when this node started logging.
223 monotonic_clock::time_point monotonic_start_time =
224 monotonic_clock::min_time;
225 realtime_clock::time_point realtime_start_time = realtime_clock::min_time;
226
227 // Corresponding time on the logger node when it started logging.
228 monotonic_clock::time_point logger_monotonic_start_time =
229 monotonic_clock::min_time;
230 realtime_clock::time_point logger_realtime_start_time =
231 realtime_clock::min_time;
Austin Schuh73340842021-07-30 22:32:06 -0700232 };
Austin Schuh58646e22021-08-23 23:51:46 -0700233
234 // Creates a new header by copying fields out of the template and combining
235 // them with the arguments provided.
236 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> MakeHeader(
237 size_t node_index, const std::vector<NewDataWriter::State> &state,
238 const UUID &parts_uuid, int parts_index);
239
240 EventLoop *event_loop_;
241 const Configuration *const configuration_;
242 const Node *const node_;
243 const size_t logger_node_index_;
244 UUID logger_node_boot_uuid_;
245 std::vector<const Node *> nodes_;
246
247 friend NewDataWriter;
248
249 // Returns the start/stop time state structure for a node and boot. We can
250 // have data from multiple boots, and it makes sense to reuse the start/stop
251 // times if we get data from the same boot again.
252 NodeState *GetNodeState(size_t node_index, const UUID &boot_uuid);
253
254 absl::btree_map<std::pair<size_t, UUID>, NodeState> node_states_;
Austin Schuh73340842021-07-30 22:32:06 -0700255
256 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> header_ =
257 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader>::Empty();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700258};
259
260// Local log namer is a simple version which only names things
261// "base_name.part#.bfbs" and increments the part number. It doesn't support
262// any other log type.
263class LocalLogNamer : public LogNamer {
264 public:
Austin Schuh5b728b72021-06-16 14:57:15 -0700265 LocalLogNamer(std::string_view base_name, aos::EventLoop *event_loop,
266 const aos::Node *node)
267 : LogNamer(event_loop->configuration(), event_loop, node),
Austin Schuhcb5601b2020-09-10 15:29:59 -0700268 base_name_(base_name),
Austin Schuh5b728b72021-06-16 14:57:15 -0700269 data_writer_(this, node,
Austin Schuh572924a2021-07-30 22:32:12 -0700270 [this](NewDataWriter *writer) {
271 writer->writer = std::make_unique<DetachedBufferWriter>(
272 absl::StrCat(base_name_, ".part",
273 writer->parts_index(), ".bfbs"),
274 std::make_unique<aos::logger::DummyEncoder>());
275 },
276 [](NewDataWriter * /*writer*/) {}) {}
Austin Schuhb8bca732021-07-30 22:32:00 -0700277
278 LocalLogNamer(const LocalLogNamer &) = delete;
279 LocalLogNamer(LocalLogNamer &&) = delete;
280 LocalLogNamer &operator=(const LocalLogNamer &) = delete;
281 LocalLogNamer &operator=(LocalLogNamer &&) = delete;
282
Brian Silverman0465fcf2020-09-24 00:29:18 -0700283 ~LocalLogNamer() override = default;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700284
Austin Schuh6bb8a822021-03-31 23:04:39 -0700285 std::string_view base_name() const final { return base_name_; }
286
287 void set_base_name(std::string_view base_name) final {
288 base_name_ = base_name;
289 }
290
Austin Schuhb8bca732021-07-30 22:32:00 -0700291 NewDataWriter *MakeWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700292
Austin Schuh73340842021-07-30 22:32:06 -0700293 void Rotate(const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700294
Austin Schuhb8bca732021-07-30 22:32:00 -0700295 NewDataWriter *MakeTimestampWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700296
Austin Schuh73340842021-07-30 22:32:06 -0700297 NewDataWriter *MakeForwardedTimestampWriter(const Channel * /*channel*/,
298 const Node * /*node*/) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700299
Austin Schuh8c399962020-12-25 21:51:45 -0800300 void WriteConfiguration(
301 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
302 std::string_view config_sha256) override;
303
Austin Schuhcb5601b2020-09-10 15:29:59 -0700304 private:
Austin Schuh6bb8a822021-03-31 23:04:39 -0700305 std::string base_name_;
Austin Schuhb8bca732021-07-30 22:32:00 -0700306
307 NewDataWriter data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700308};
309
310// Log namer which uses a config and a base name to name a bunch of files.
311class MultiNodeLogNamer : public LogNamer {
312 public:
Austin Schuha499cea2021-07-31 19:49:53 -0700313 MultiNodeLogNamer(std::string_view base_name, EventLoop *event_loop);
Austin Schuh5b728b72021-06-16 14:57:15 -0700314 MultiNodeLogNamer(std::string_view base_name,
315 const Configuration *configuration, EventLoop *event_loop,
316 const Node *node);
Brian Silvermancb805822020-10-06 17:43:35 -0700317 ~MultiNodeLogNamer() override;
318
Austin Schuh6bb8a822021-03-31 23:04:39 -0700319 std::string_view base_name() const final { return base_name_; }
320
321 void set_base_name(std::string_view base_name) final {
322 old_base_name_ = base_name_;
323 base_name_ = base_name;
324 }
Brian Silvermancb805822020-10-06 17:43:35 -0700325
Brian Silverman48deab12020-09-30 18:39:28 -0700326 // If temp_suffix is set, then this will write files under names beginning
327 // with the specified suffix, and then rename them to the desired name after
328 // they are fully written.
329 //
330 // This is useful to enable incremental copying of the log files.
331 //
332 // Defaults to writing directly to the final filename.
Brian Silvermancb805822020-10-06 17:43:35 -0700333 void set_temp_suffix(std::string_view temp_suffix) {
334 temp_suffix_ = temp_suffix;
335 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700336
Brian Silvermancb805822020-10-06 17:43:35 -0700337 // Sets the function for creating encoders.
338 //
339 // Defaults to just creating DummyEncoders.
340 void set_encoder_factory(
341 std::function<std::unique_ptr<DetachedBufferEncoder>()> encoder_factory) {
342 encoder_factory_ = std::move(encoder_factory);
343 }
344
345 // Sets an additional file extension.
346 //
347 // Defaults to nothing.
348 void set_extension(std::string_view extension) { extension_ = extension; }
Brian Silverman1f345222020-09-24 21:14:48 -0700349
Brian Silvermana621f522020-09-30 16:52:43 -0700350 // A list of all the filenames we've written.
351 //
352 // This only includes the part after base_name().
353 const std::vector<std::string> &all_filenames() const {
354 return all_filenames_;
355 }
356
Austin Schuh73340842021-07-30 22:32:06 -0700357 void Rotate(const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700358
Austin Schuh8c399962020-12-25 21:51:45 -0800359 void WriteConfiguration(
360 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
361 std::string_view config_sha256) override;
362
Austin Schuhb8bca732021-07-30 22:32:00 -0700363 NewDataWriter *MakeWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700364
Austin Schuhb8bca732021-07-30 22:32:00 -0700365 NewDataWriter *MakeForwardedTimestampWriter(const Channel *channel,
Austin Schuh73340842021-07-30 22:32:06 -0700366 const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700367
Austin Schuhb8bca732021-07-30 22:32:00 -0700368 NewDataWriter *MakeTimestampWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700369
Brian Silverman0465fcf2020-09-24 00:29:18 -0700370 // Indicates that at least one file ran out of space. Once this happens, we
371 // stop trying to open new files, to avoid writing any files with holes from
372 // previous parts.
373 //
374 // Besides this function, this object will silently stop logging data when
375 // this occurs. If you want to ensure log files are complete, you must call
376 // this method.
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700377 bool ran_out_of_space() const {
378 return accumulate_data_writers<bool>(
Austin Schuhb8bca732021-07-30 22:32:00 -0700379 ran_out_of_space_, [](bool x, const NewDataWriter &data_writer) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700380 return x ||
381 (data_writer.writer && data_writer.writer->ran_out_of_space());
382 });
383 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700384
Brian Silverman1f345222020-09-24 21:14:48 -0700385 // Returns the maximum total_bytes() value for all existing
386 // DetachedBufferWriters.
387 //
388 // Returns 0 if no files are open.
389 size_t maximum_total_bytes() const {
Brian Silvermancb805822020-10-06 17:43:35 -0700390 return accumulate_data_writers<size_t>(
Austin Schuhb8bca732021-07-30 22:32:00 -0700391 0, [](size_t x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700392 return std::max(x, data_writer.writer->total_bytes());
393 });
Brian Silverman1f345222020-09-24 21:14:48 -0700394 }
395
Brian Silverman0465fcf2020-09-24 00:29:18 -0700396 // Closes all existing log files. No more data may be written after this.
397 //
398 // This may set ran_out_of_space().
399 void Close();
400
Brian Silvermancb805822020-10-06 17:43:35 -0700401 // Accessors for various statistics. See the identically-named methods in
402 // DetachedBufferWriter for documentation. These are aggregated across all
403 // past and present DetachedBufferWriters.
404 std::chrono::nanoseconds max_write_time() const {
405 return accumulate_data_writers(
406 max_write_time_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700407 [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700408 return std::max(x, data_writer.writer->max_write_time());
409 });
410 }
411 int max_write_time_bytes() const {
412 return std::get<0>(accumulate_data_writers(
413 std::make_tuple(max_write_time_bytes_, max_write_time_),
414 [](std::tuple<int, std::chrono::nanoseconds> x,
Austin Schuhb8bca732021-07-30 22:32:00 -0700415 const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700416 if (data_writer.writer->max_write_time() > std::get<1>(x)) {
417 return std::make_tuple(data_writer.writer->max_write_time_bytes(),
418 data_writer.writer->max_write_time());
419 }
420 return x;
421 }));
422 }
423 int max_write_time_messages() const {
424 return std::get<0>(accumulate_data_writers(
425 std::make_tuple(max_write_time_messages_, max_write_time_),
426 [](std::tuple<int, std::chrono::nanoseconds> x,
Austin Schuhb8bca732021-07-30 22:32:00 -0700427 const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700428 if (data_writer.writer->max_write_time() > std::get<1>(x)) {
429 return std::make_tuple(
430 data_writer.writer->max_write_time_messages(),
431 data_writer.writer->max_write_time());
432 }
433 return x;
434 }));
435 }
436 std::chrono::nanoseconds total_write_time() const {
437 return accumulate_data_writers(
438 total_write_time_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700439 [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700440 return x + data_writer.writer->total_write_time();
441 });
442 }
443 int total_write_count() const {
444 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700445 total_write_count_, [](int x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700446 return x + data_writer.writer->total_write_count();
447 });
448 }
449 int total_write_messages() const {
450 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700451 total_write_messages_, [](int x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700452 return x + data_writer.writer->total_write_messages();
453 });
454 }
455 int total_write_bytes() const {
456 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700457 total_write_bytes_, [](int x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700458 return x + data_writer.writer->total_write_bytes();
459 });
460 }
461
462 void ResetStatistics();
463
Austin Schuhcb5601b2020-09-10 15:29:59 -0700464 private:
Austin Schuhcb5601b2020-09-10 15:29:59 -0700465 // Opens up a writer for timestamps forwarded back.
466 void OpenForwardedTimestampWriter(const Channel *channel,
Austin Schuhb8bca732021-07-30 22:32:00 -0700467 NewDataWriter *data_writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700468
469 // Opens up a writer for remote data.
Austin Schuhb8bca732021-07-30 22:32:00 -0700470 void OpenWriter(const Channel *channel, NewDataWriter *data_writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700471
472 // Opens the main data writer file for this node responsible for data_writer_.
Brian Silvermana621f522020-09-30 16:52:43 -0700473 void OpenDataWriter();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700474
Brian Silvermana621f522020-09-30 16:52:43 -0700475 void CreateBufferWriter(std::string_view path,
Brian Silverman0465fcf2020-09-24 00:29:18 -0700476 std::unique_ptr<DetachedBufferWriter> *destination);
477
Brian Silverman48deab12020-09-30 18:39:28 -0700478 void RenameTempFile(DetachedBufferWriter *destination);
479
Brian Silvermancb805822020-10-06 17:43:35 -0700480 void CloseWriter(std::unique_ptr<DetachedBufferWriter> *writer_pointer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700481
Brian Silvermancb805822020-10-06 17:43:35 -0700482 // A version of std::accumulate which operates over all of our DataWriters.
483 template <typename T, typename BinaryOperation>
484 T accumulate_data_writers(T t, BinaryOperation op) const {
Austin Schuhb8bca732021-07-30 22:32:00 -0700485 for (const std::pair<const Channel *const, NewDataWriter> &data_writer :
Brian Silvermancb805822020-10-06 17:43:35 -0700486 data_writers_) {
Austin Schuhad0cfc32020-12-21 12:34:26 -0800487 if (!data_writer.second.writer) continue;
Brian Silvermancb805822020-10-06 17:43:35 -0700488 t = op(std::move(t), data_writer.second);
489 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700490 if (data_writer_) {
491 t = op(std::move(t), *data_writer_);
Brian Silvermancb805822020-10-06 17:43:35 -0700492 }
493 return t;
494 }
495
Austin Schuh6bb8a822021-03-31 23:04:39 -0700496 std::string base_name_;
497 std::string old_base_name_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700498
Brian Silverman0465fcf2020-09-24 00:29:18 -0700499 bool ran_out_of_space_ = false;
Brian Silvermana621f522020-09-30 16:52:43 -0700500 std::vector<std::string> all_filenames_;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700501
Brian Silvermancb805822020-10-06 17:43:35 -0700502 std::string temp_suffix_;
503 std::function<std::unique_ptr<DetachedBufferEncoder>()> encoder_factory_ =
504 []() { return std::make_unique<DummyEncoder>(); };
505 std::string extension_;
506
507 // Storage for statistics from previously-rotated DetachedBufferWriters.
508 std::chrono::nanoseconds max_write_time_ = std::chrono::nanoseconds::zero();
509 int max_write_time_bytes_ = -1;
510 int max_write_time_messages_ = -1;
511 std::chrono::nanoseconds total_write_time_ = std::chrono::nanoseconds::zero();
512 int total_write_count_ = 0;
513 int total_write_messages_ = 0;
514 int total_write_bytes_ = 0;
515
Austin Schuhcb5601b2020-09-10 15:29:59 -0700516 // File to write both delivery timestamps and local data to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700517 std::unique_ptr<NewDataWriter> data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700518
Austin Schuhb8bca732021-07-30 22:32:00 -0700519 std::map<const Channel *, NewDataWriter> data_writers_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700520};
521
522} // namespace logger
523} // namespace aos
524
525#endif // AOS_EVENTS_LOGGING_LOG_NAMER_H_