blob: 7947ebe6714bf12a2836bf14f86aa66b890c0644 [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 Schuhf5f99f32022-02-07 20:05:37 -080039 NewDataWriter(LogNamer *log_namer, const Node *node, const Node *logger_node,
Austin Schuh572924a2021-07-30 22:32:12 -070040 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 Schuhf5f99f32022-02-07 20:05:37 -080053 // Updates all the metadata in the log file about the remote node which this
54 // message is from.
Austin Schuh72211ae2021-08-05 14:02:30 -070055 void UpdateRemote(size_t remote_node_index, const UUID &remote_node_boot_uuid,
56 monotonic_clock::time_point monotonic_remote_time,
57 monotonic_clock::time_point monotonic_event_time,
Austin Schuhf5f99f32022-02-07 20:05:37 -080058 bool reliable,
59 monotonic_clock::time_point monotonic_timestamp_time =
60 monotonic_clock::min_time);
Austin Schuh572924a2021-07-30 22:32:12 -070061 // Queues up a message with the provided boot UUID.
Austin Schuhe46492f2021-07-31 19:49:41 -070062 void QueueMessage(flatbuffers::FlatBufferBuilder *fbb,
63 const UUID &node_boot_uuid,
64 aos::monotonic_clock::time_point now);
Austin Schuhb8bca732021-07-30 22:32:00 -070065
Austin Schuh5e14d842022-01-21 12:02:15 -080066 // Updates the current boot for the source node. This is useful when you want
67 // to queue a message that may trigger a reboot rotation, but then need to
68 // update the remote timestamps.
69 void UpdateBoot(const UUID &source_node_boot_uuid);
70
Austin Schuh572924a2021-07-30 22:32:12 -070071 // Returns the filename of the writer.
Austin Schuh58646e22021-08-23 23:51:46 -070072 std::string_view filename() const {
73 return writer ? writer->filename() : "(closed)";
74 }
Austin Schuhb8bca732021-07-30 22:32:00 -070075
Austin Schuh572924a2021-07-30 22:32:12 -070076 void Close();
Austin Schuhb8bca732021-07-30 22:32:00 -070077
78 std::unique_ptr<DetachedBufferWriter> writer = nullptr;
Austin Schuh572924a2021-07-30 22:32:12 -070079
80 size_t node_index() const { return node_index_; }
81 const UUID &parts_uuid() const { return parts_uuid_; }
82 size_t parts_index() const { return parts_index_; }
83 const Node *node() const { return node_; }
Austin Schuhb8bca732021-07-30 22:32:00 -070084
Austin Schuh72211ae2021-08-05 14:02:30 -070085 // Datastructure used to capture all the information about a remote node.
86 struct State {
87 // Boot UUID of the node.
88 UUID boot_uuid = UUID::Zero();
89 // Timestamp on the remote monotonic clock of the oldest message sent to
90 // node_index_.
91 monotonic_clock::time_point oldest_remote_monotonic_timestamp =
92 monotonic_clock::max_time;
93 // Timestamp on the local monotonic clock of the message in
94 // oldest_remote_monotonic_timestamp.
95 monotonic_clock::time_point oldest_local_monotonic_timestamp =
96 monotonic_clock::max_time;
97 // Timestamp on the remote monotonic clock of the oldest message sent to
98 // node_index_, excluding messages forwarded with time_to_live() == 0.
99 monotonic_clock::time_point oldest_remote_unreliable_monotonic_timestamp =
100 monotonic_clock::max_time;
101 // Timestamp on the local monotonic clock of the message in
102 // oldest_local_unreliable_monotonic_timestamp.
103 monotonic_clock::time_point oldest_local_unreliable_monotonic_timestamp =
104 monotonic_clock::max_time;
Austin Schuhbfe6c572022-01-27 20:48:20 -0800105
106 // Timestamp on the remote monotonic clock of the oldest message sent to
107 // node_index_, only including messages forwarded with time_to_live() == 0.
108 monotonic_clock::time_point oldest_remote_reliable_monotonic_timestamp =
109 monotonic_clock::max_time;
110 // Timestamp on the local monotonic clock of the message in
111 // oldest_local_reliable_monotonic_timestamp.
112 monotonic_clock::time_point oldest_local_reliable_monotonic_timestamp =
113 monotonic_clock::max_time;
Austin Schuhf5f99f32022-02-07 20:05:37 -0800114
115 // Timestamp on the remote monotonic clock of the oldest message timestamp
116 // sent back to logger_node_index_. The remote here will be the node this
117 // part is from the perspective of, ie node_index_.
118 monotonic_clock::time_point
119 oldest_logger_remote_unreliable_monotonic_timestamp =
120 monotonic_clock::max_time;
121 // The time on the monotonic clock of the logger when this timestamp made it
122 // back to the logger (logger_node_index_).
123 monotonic_clock::time_point
124 oldest_logger_local_unreliable_monotonic_timestamp =
125 monotonic_clock::max_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700126 };
127
Austin Schuhb8bca732021-07-30 22:32:00 -0700128 private:
Austin Schuhe46492f2021-07-31 19:49:41 -0700129 // Signals that a node has rebooted.
Austin Schuh5e14d842022-01-21 12:02:15 -0800130 void Reboot(const UUID &source_node_boot_uuid);
Austin Schuhe46492f2021-07-31 19:49:41 -0700131
Austin Schuh572924a2021-07-30 22:32:12 -0700132 void QueueHeader(
133 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> &&header);
134
Austin Schuhe46492f2021-07-31 19:49:41 -0700135 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> MakeHeader();
136
Austin Schuh58646e22021-08-23 23:51:46 -0700137 monotonic_clock::time_point monotonic_start_time_ = monotonic_clock::min_time;
138
Austin Schuh577610e2021-12-08 12:07:19 -0800139 const Node *node_ = nullptr;
140 size_t node_index_ = 0;
Austin Schuhf5f99f32022-02-07 20:05:37 -0800141 size_t logger_node_index_ = 0;
Austin Schuh572924a2021-07-30 22:32:12 -0700142 LogNamer *log_namer_;
143 UUID parts_uuid_ = UUID::Random();
144 size_t parts_index_ = 0;
145
Austin Schuhb8bca732021-07-30 22:32:00 -0700146 std::function<void(NewDataWriter *)> reopen_;
147 std::function<void(NewDataWriter *)> close_;
Austin Schuh572924a2021-07-30 22:32:12 -0700148 bool header_written_ = false;
Austin Schuhe46492f2021-07-31 19:49:41 -0700149
Austin Schuh72211ae2021-08-05 14:02:30 -0700150 std::vector<State> state_;
Austin Schuhb8bca732021-07-30 22:32:00 -0700151};
152
Austin Schuhcb5601b2020-09-10 15:29:59 -0700153// Interface describing how to name, track, and add headers to log file parts.
154class LogNamer {
155 public:
156 // Constructs a LogNamer with the primary node (ie the one the logger runs on)
157 // being node.
Austin Schuh5b728b72021-06-16 14:57:15 -0700158 LogNamer(const aos::Configuration *configuration, EventLoop *event_loop,
159 const aos::Node *node)
Austin Schuha499cea2021-07-31 19:49:53 -0700160 : event_loop_(event_loop),
Austin Schuh5b728b72021-06-16 14:57:15 -0700161 configuration_(configuration),
162 node_(node),
Austin Schuha499cea2021-07-31 19:49:53 -0700163 logger_node_index_(configuration::GetNodeIndex(configuration_, node_)) {
Austin Schuh73340842021-07-30 22:32:06 -0700164 nodes_.emplace_back(node_);
Austin Schuh73340842021-07-30 22:32:06 -0700165 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700166 virtual ~LogNamer() {}
167
Austin Schuh6bb8a822021-03-31 23:04:39 -0700168 virtual std::string_view base_name() const = 0;
169
170 // Rotate should be called at least once in between calls to set_base_name.
171 // Otherwise temporary files will not be recoverable.
172 // Rotate is called by Logger::RenameLogBase, which is currently the only user
173 // of this method.
174 // Only renaming the folder is supported, not the file base name.
175 virtual void set_base_name(std::string_view base_name) = 0;
176
Brian Silverman87ac0402020-09-17 14:47:01 -0700177 // Returns a writer for writing data from messages on this channel (on the
178 // primary node).
179 //
180 // The returned pointer will stay valid across rotations, but the object it
181 // points to will be assigned to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700182 virtual NewDataWriter *MakeWriter(const Channel *channel) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700183
Brian Silverman87ac0402020-09-17 14:47:01 -0700184 // Returns a writer for writing timestamps from messages on this channel (on
185 // the primary node).
186 //
187 // The returned pointer will stay valid across rotations, but the object it
188 // points to will be assigned to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700189 virtual NewDataWriter *MakeTimestampWriter(const Channel *channel) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700190
191 // Returns a writer for writing timestamps delivered over the special
192 // /aos/remote_timestamps/* channels. node is the node that the timestamps
Brian Silverman87ac0402020-09-17 14:47:01 -0700193 // are forwarded back from (to the primary node).
194 //
195 // The returned pointer will stay valid across rotations, but the object it
196 // points to will be assigned to.
Austin Schuh73340842021-07-30 22:32:06 -0700197 virtual NewDataWriter *MakeForwardedTimestampWriter(const Channel *channel,
198 const Node *node) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700199
Austin Schuh73340842021-07-30 22:32:06 -0700200 // Rotates all log files for the provided node.
201 virtual void Rotate(const Node *node) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700202
203 // Returns all the nodes that data is being written for.
204 const std::vector<const Node *> &nodes() const { return nodes_; }
205
206 // Returns the node the logger is running on.
207 const Node *node() const { return node_; }
Austin Schuhe46492f2021-07-31 19:49:41 -0700208 const UUID &logger_node_boot_uuid() const { return logger_node_boot_uuid_; }
209 size_t logger_node_index() const { return logger_node_index_; }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700210
Austin Schuh8c399962020-12-25 21:51:45 -0800211 // Writes out the nested Configuration object to the config file location.
212 virtual void WriteConfiguration(
213 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
214 std::string_view config_sha256) = 0;
215
Austin Schuh73340842021-07-30 22:32:06 -0700216 void SetHeaderTemplate(
217 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> header) {
218 header_ = std::move(header);
Austin Schuhe46492f2021-07-31 19:49:41 -0700219 logger_node_boot_uuid_ =
220 UUID::FromString(header_.message().logger_node_boot_uuid());
Austin Schuh73340842021-07-30 22:32:06 -0700221 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700222
Austin Schuh60e77942022-05-16 17:48:24 -0700223 void ClearStartTimes() { node_states_.clear(); }
Austin Schuh58646e22021-08-23 23:51:46 -0700224
225 void SetStartTimes(size_t node_index, const UUID &boot_uuid,
Austin Schuh73340842021-07-30 22:32:06 -0700226 monotonic_clock::time_point monotonic_start_time,
227 realtime_clock::time_point realtime_start_time,
228 monotonic_clock::time_point logger_monotonic_start_time,
229 realtime_clock::time_point logger_realtime_start_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700230 VLOG(1) << "Setting node " << node_index << " to start time "
231 << monotonic_start_time << " rt " << realtime_start_time << " UUID "
232 << boot_uuid;
233 NodeState *node_state = GetNodeState(node_index, boot_uuid);
234 node_state->monotonic_start_time = monotonic_start_time;
235 node_state->realtime_start_time = realtime_start_time;
236 node_state->logger_monotonic_start_time = logger_monotonic_start_time;
237 node_state->logger_realtime_start_time = logger_realtime_start_time;
Austin Schuh73340842021-07-30 22:32:06 -0700238 }
239
Austin Schuh58646e22021-08-23 23:51:46 -0700240 monotonic_clock::time_point monotonic_start_time(size_t node_index,
241 const UUID &boot_uuid) {
242 DCHECK_NE(boot_uuid, UUID::Zero());
243
244 NodeState *node_state = GetNodeState(node_index, boot_uuid);
245 return node_state->monotonic_start_time;
Austin Schuh73340842021-07-30 22:32:06 -0700246 }
247
Austin Schuh73340842021-07-30 22:32:06 -0700248 protected:
Austin Schuh73340842021-07-30 22:32:06 -0700249 // Structure with state per node about times and such.
Austin Schuh73340842021-07-30 22:32:06 -0700250 struct NodeState {
251 // Time when this node started logging.
252 monotonic_clock::time_point monotonic_start_time =
253 monotonic_clock::min_time;
254 realtime_clock::time_point realtime_start_time = realtime_clock::min_time;
255
256 // Corresponding time on the logger node when it started logging.
257 monotonic_clock::time_point logger_monotonic_start_time =
258 monotonic_clock::min_time;
259 realtime_clock::time_point logger_realtime_start_time =
260 realtime_clock::min_time;
Austin Schuh73340842021-07-30 22:32:06 -0700261 };
Austin Schuh58646e22021-08-23 23:51:46 -0700262
263 // Creates a new header by copying fields out of the template and combining
264 // them with the arguments provided.
265 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> MakeHeader(
266 size_t node_index, const std::vector<NewDataWriter::State> &state,
267 const UUID &parts_uuid, int parts_index);
268
269 EventLoop *event_loop_;
270 const Configuration *const configuration_;
271 const Node *const node_;
272 const size_t logger_node_index_;
273 UUID logger_node_boot_uuid_;
274 std::vector<const Node *> nodes_;
275
276 friend NewDataWriter;
277
278 // Returns the start/stop time state structure for a node and boot. We can
279 // have data from multiple boots, and it makes sense to reuse the start/stop
280 // times if we get data from the same boot again.
281 NodeState *GetNodeState(size_t node_index, const UUID &boot_uuid);
282
283 absl::btree_map<std::pair<size_t, UUID>, NodeState> node_states_;
Austin Schuh73340842021-07-30 22:32:06 -0700284
285 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> header_ =
286 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader>::Empty();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700287};
288
289// Local log namer is a simple version which only names things
290// "base_name.part#.bfbs" and increments the part number. It doesn't support
291// any other log type.
292class LocalLogNamer : public LogNamer {
293 public:
Austin Schuh5b728b72021-06-16 14:57:15 -0700294 LocalLogNamer(std::string_view base_name, aos::EventLoop *event_loop,
295 const aos::Node *node)
296 : LogNamer(event_loop->configuration(), event_loop, node),
Austin Schuhcb5601b2020-09-10 15:29:59 -0700297 base_name_(base_name),
Austin Schuhf5f99f32022-02-07 20:05:37 -0800298 data_writer_(
299 this, node, event_loop->node(),
300 [this](NewDataWriter *writer) {
301 writer->writer = std::make_unique<DetachedBufferWriter>(
302 absl::StrCat(base_name_, ".part", writer->parts_index(),
303 ".bfbs"),
304 std::make_unique<aos::logger::DummyEncoder>());
305 },
306 [](NewDataWriter * /*writer*/) {}) {}
Austin Schuhb8bca732021-07-30 22:32:00 -0700307
308 LocalLogNamer(const LocalLogNamer &) = delete;
309 LocalLogNamer(LocalLogNamer &&) = delete;
310 LocalLogNamer &operator=(const LocalLogNamer &) = delete;
311 LocalLogNamer &operator=(LocalLogNamer &&) = delete;
312
Brian Silverman0465fcf2020-09-24 00:29:18 -0700313 ~LocalLogNamer() override = default;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700314
Austin Schuh6bb8a822021-03-31 23:04:39 -0700315 std::string_view base_name() const final { return base_name_; }
316
317 void set_base_name(std::string_view base_name) final {
318 base_name_ = base_name;
319 }
320
Austin Schuhb8bca732021-07-30 22:32:00 -0700321 NewDataWriter *MakeWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700322
Austin Schuh73340842021-07-30 22:32:06 -0700323 void Rotate(const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700324
Austin Schuhb8bca732021-07-30 22:32:00 -0700325 NewDataWriter *MakeTimestampWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700326
Austin Schuh73340842021-07-30 22:32:06 -0700327 NewDataWriter *MakeForwardedTimestampWriter(const Channel * /*channel*/,
328 const Node * /*node*/) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700329
Austin Schuh8c399962020-12-25 21:51:45 -0800330 void WriteConfiguration(
331 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
332 std::string_view config_sha256) override;
333
Austin Schuhcb5601b2020-09-10 15:29:59 -0700334 private:
Austin Schuh6bb8a822021-03-31 23:04:39 -0700335 std::string base_name_;
Austin Schuhb8bca732021-07-30 22:32:00 -0700336
337 NewDataWriter data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700338};
339
340// Log namer which uses a config and a base name to name a bunch of files.
341class MultiNodeLogNamer : public LogNamer {
342 public:
Austin Schuha499cea2021-07-31 19:49:53 -0700343 MultiNodeLogNamer(std::string_view base_name, EventLoop *event_loop);
Austin Schuh5b728b72021-06-16 14:57:15 -0700344 MultiNodeLogNamer(std::string_view base_name,
345 const Configuration *configuration, EventLoop *event_loop,
346 const Node *node);
Brian Silvermancb805822020-10-06 17:43:35 -0700347 ~MultiNodeLogNamer() override;
348
Austin Schuh6bb8a822021-03-31 23:04:39 -0700349 std::string_view base_name() const final { return base_name_; }
350
351 void set_base_name(std::string_view base_name) final {
352 old_base_name_ = base_name_;
353 base_name_ = base_name;
354 }
Brian Silvermancb805822020-10-06 17:43:35 -0700355
Brian Silverman48deab12020-09-30 18:39:28 -0700356 // If temp_suffix is set, then this will write files under names beginning
357 // with the specified suffix, and then rename them to the desired name after
358 // they are fully written.
359 //
360 // This is useful to enable incremental copying of the log files.
361 //
362 // Defaults to writing directly to the final filename.
Brian Silvermancb805822020-10-06 17:43:35 -0700363 void set_temp_suffix(std::string_view temp_suffix) {
364 temp_suffix_ = temp_suffix;
365 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700366
Brian Silvermancb805822020-10-06 17:43:35 -0700367 // Sets the function for creating encoders.
368 //
369 // Defaults to just creating DummyEncoders.
370 void set_encoder_factory(
371 std::function<std::unique_ptr<DetachedBufferEncoder>()> encoder_factory) {
372 encoder_factory_ = std::move(encoder_factory);
373 }
374
375 // Sets an additional file extension.
376 //
377 // Defaults to nothing.
378 void set_extension(std::string_view extension) { extension_ = extension; }
Brian Silverman1f345222020-09-24 21:14:48 -0700379
Brian Silvermana621f522020-09-30 16:52:43 -0700380 // A list of all the filenames we've written.
381 //
382 // This only includes the part after base_name().
383 const std::vector<std::string> &all_filenames() const {
384 return all_filenames_;
385 }
386
Austin Schuh73340842021-07-30 22:32:06 -0700387 void Rotate(const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700388
Austin Schuh8c399962020-12-25 21:51:45 -0800389 void WriteConfiguration(
390 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
391 std::string_view config_sha256) override;
392
Austin Schuhb8bca732021-07-30 22:32:00 -0700393 NewDataWriter *MakeWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700394
Austin Schuhb8bca732021-07-30 22:32:00 -0700395 NewDataWriter *MakeForwardedTimestampWriter(const Channel *channel,
Austin Schuh73340842021-07-30 22:32:06 -0700396 const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700397
Austin Schuhb8bca732021-07-30 22:32:00 -0700398 NewDataWriter *MakeTimestampWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700399
Brian Silverman0465fcf2020-09-24 00:29:18 -0700400 // Indicates that at least one file ran out of space. Once this happens, we
401 // stop trying to open new files, to avoid writing any files with holes from
402 // previous parts.
403 //
404 // Besides this function, this object will silently stop logging data when
405 // this occurs. If you want to ensure log files are complete, you must call
406 // this method.
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700407 bool ran_out_of_space() const {
408 return accumulate_data_writers<bool>(
Austin Schuhb8bca732021-07-30 22:32:00 -0700409 ran_out_of_space_, [](bool x, const NewDataWriter &data_writer) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700410 return x ||
411 (data_writer.writer && data_writer.writer->ran_out_of_space());
412 });
413 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700414
Brian Silverman1f345222020-09-24 21:14:48 -0700415 // Returns the maximum total_bytes() value for all existing
416 // DetachedBufferWriters.
417 //
418 // Returns 0 if no files are open.
419 size_t maximum_total_bytes() const {
Brian Silvermancb805822020-10-06 17:43:35 -0700420 return accumulate_data_writers<size_t>(
Austin Schuhb8bca732021-07-30 22:32:00 -0700421 0, [](size_t x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700422 return std::max(x, data_writer.writer->total_bytes());
423 });
Brian Silverman1f345222020-09-24 21:14:48 -0700424 }
425
Brian Silverman0465fcf2020-09-24 00:29:18 -0700426 // Closes all existing log files. No more data may be written after this.
427 //
428 // This may set ran_out_of_space().
429 void Close();
430
Brian Silvermancb805822020-10-06 17:43:35 -0700431 // Accessors for various statistics. See the identically-named methods in
432 // DetachedBufferWriter for documentation. These are aggregated across all
433 // past and present DetachedBufferWriters.
434 std::chrono::nanoseconds max_write_time() const {
435 return accumulate_data_writers(
436 max_write_time_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700437 [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700438 return std::max(x, data_writer.writer->max_write_time());
439 });
440 }
441 int max_write_time_bytes() const {
442 return std::get<0>(accumulate_data_writers(
443 std::make_tuple(max_write_time_bytes_, max_write_time_),
444 [](std::tuple<int, std::chrono::nanoseconds> x,
Austin Schuhb8bca732021-07-30 22:32:00 -0700445 const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700446 if (data_writer.writer->max_write_time() > std::get<1>(x)) {
447 return std::make_tuple(data_writer.writer->max_write_time_bytes(),
448 data_writer.writer->max_write_time());
449 }
450 return x;
451 }));
452 }
453 int max_write_time_messages() const {
454 return std::get<0>(accumulate_data_writers(
455 std::make_tuple(max_write_time_messages_, max_write_time_),
456 [](std::tuple<int, std::chrono::nanoseconds> x,
Austin Schuhb8bca732021-07-30 22:32:00 -0700457 const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700458 if (data_writer.writer->max_write_time() > std::get<1>(x)) {
459 return std::make_tuple(
460 data_writer.writer->max_write_time_messages(),
461 data_writer.writer->max_write_time());
462 }
463 return x;
464 }));
465 }
466 std::chrono::nanoseconds total_write_time() const {
467 return accumulate_data_writers(
468 total_write_time_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700469 [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700470 return x + data_writer.writer->total_write_time();
471 });
472 }
473 int total_write_count() const {
474 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700475 total_write_count_, [](int x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700476 return x + data_writer.writer->total_write_count();
477 });
478 }
479 int total_write_messages() const {
480 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700481 total_write_messages_, [](int x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700482 return x + data_writer.writer->total_write_messages();
483 });
484 }
485 int total_write_bytes() const {
486 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700487 total_write_bytes_, [](int x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700488 return x + data_writer.writer->total_write_bytes();
489 });
490 }
491
492 void ResetStatistics();
493
Austin Schuhcb5601b2020-09-10 15:29:59 -0700494 private:
Austin Schuhcb5601b2020-09-10 15:29:59 -0700495 // Opens up a writer for timestamps forwarded back.
496 void OpenForwardedTimestampWriter(const Channel *channel,
Austin Schuhb8bca732021-07-30 22:32:00 -0700497 NewDataWriter *data_writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700498
499 // Opens up a writer for remote data.
Austin Schuhb8bca732021-07-30 22:32:00 -0700500 void OpenWriter(const Channel *channel, NewDataWriter *data_writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700501
502 // Opens the main data writer file for this node responsible for data_writer_.
Brian Silvermana621f522020-09-30 16:52:43 -0700503 void OpenDataWriter();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700504
Brian Silvermana621f522020-09-30 16:52:43 -0700505 void CreateBufferWriter(std::string_view path,
Brian Silverman0465fcf2020-09-24 00:29:18 -0700506 std::unique_ptr<DetachedBufferWriter> *destination);
507
Brian Silverman48deab12020-09-30 18:39:28 -0700508 void RenameTempFile(DetachedBufferWriter *destination);
509
Brian Silvermancb805822020-10-06 17:43:35 -0700510 void CloseWriter(std::unique_ptr<DetachedBufferWriter> *writer_pointer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700511
Brian Silvermancb805822020-10-06 17:43:35 -0700512 // A version of std::accumulate which operates over all of our DataWriters.
513 template <typename T, typename BinaryOperation>
514 T accumulate_data_writers(T t, BinaryOperation op) const {
Austin Schuhb8bca732021-07-30 22:32:00 -0700515 for (const std::pair<const Channel *const, NewDataWriter> &data_writer :
Brian Silvermancb805822020-10-06 17:43:35 -0700516 data_writers_) {
Austin Schuhad0cfc32020-12-21 12:34:26 -0800517 if (!data_writer.second.writer) continue;
Brian Silvermancb805822020-10-06 17:43:35 -0700518 t = op(std::move(t), data_writer.second);
519 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700520 if (data_writer_) {
521 t = op(std::move(t), *data_writer_);
Brian Silvermancb805822020-10-06 17:43:35 -0700522 }
523 return t;
524 }
525
Austin Schuh6bb8a822021-03-31 23:04:39 -0700526 std::string base_name_;
527 std::string old_base_name_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700528
Brian Silverman0465fcf2020-09-24 00:29:18 -0700529 bool ran_out_of_space_ = false;
Brian Silvermana621f522020-09-30 16:52:43 -0700530 std::vector<std::string> all_filenames_;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700531
Brian Silvermancb805822020-10-06 17:43:35 -0700532 std::string temp_suffix_;
533 std::function<std::unique_ptr<DetachedBufferEncoder>()> encoder_factory_ =
534 []() { return std::make_unique<DummyEncoder>(); };
535 std::string extension_;
536
537 // Storage for statistics from previously-rotated DetachedBufferWriters.
538 std::chrono::nanoseconds max_write_time_ = std::chrono::nanoseconds::zero();
539 int max_write_time_bytes_ = -1;
540 int max_write_time_messages_ = -1;
541 std::chrono::nanoseconds total_write_time_ = std::chrono::nanoseconds::zero();
542 int total_write_count_ = 0;
543 int total_write_messages_ = 0;
544 int total_write_bytes_ = 0;
545
Austin Schuhcb5601b2020-09-10 15:29:59 -0700546 // File to write both delivery timestamps and local data to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700547 std::unique_ptr<NewDataWriter> data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700548
Austin Schuhb8bca732021-07-30 22:32:00 -0700549 std::map<const Channel *, NewDataWriter> data_writers_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700550};
551
552} // namespace logger
553} // namespace aos
554
555#endif // AOS_EVENTS_LOGGING_LOG_NAMER_H_