blob: c0c7c7378f26b1f824e20098ebf66626c0d1b3fe [file] [log] [blame]
Austin Schuhcb5601b2020-09-10 15:29:59 -07001#include "aos/events/logging/log_namer.h"
2
3#include <functional>
4#include <map>
5#include <memory>
6#include <string_view>
7#include <vector>
8
9#include "absl/strings/str_cat.h"
10#include "aos/events/logging/logfile_utils.h"
11#include "aos/events/logging/logger_generated.h"
Austin Schuh73340842021-07-30 22:32:06 -070012#include "aos/flatbuffer_merge.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#include "glog/logging.h"
16
17namespace aos {
18namespace logger {
19
Austin Schuh572924a2021-07-30 22:32:12 -070020NewDataWriter::NewDataWriter(LogNamer *log_namer, const Node *node,
Austin Schuhf5f99f32022-02-07 20:05:37 -080021 const Node *logger_node,
Austin Schuh572924a2021-07-30 22:32:12 -070022 std::function<void(NewDataWriter *)> reopen,
Austin Schuh48d10d62022-10-16 22:19:23 -070023 std::function<void(NewDataWriter *)> close,
24 size_t max_message_size)
Austin Schuh572924a2021-07-30 22:32:12 -070025 : node_(node),
26 node_index_(configuration::GetNodeIndex(log_namer->configuration_, node)),
Austin Schuhf5f99f32022-02-07 20:05:37 -080027 logger_node_index_(
28 configuration::GetNodeIndex(log_namer->configuration_, logger_node)),
Austin Schuh572924a2021-07-30 22:32:12 -070029 log_namer_(log_namer),
30 reopen_(std::move(reopen)),
Austin Schuh48d10d62022-10-16 22:19:23 -070031 close_(std::move(close)),
32 max_message_size_(max_message_size) {
Austin Schuh72211ae2021-08-05 14:02:30 -070033 state_.resize(configuration::NodesCount(log_namer->configuration_));
34 CHECK_LT(node_index_, state_.size());
Austin Schuh572924a2021-07-30 22:32:12 -070035}
36
37NewDataWriter::~NewDataWriter() {
38 if (writer) {
39 Close();
40 }
41}
42
43void NewDataWriter::Rotate() {
Austin Schuhe46492f2021-07-31 19:49:41 -070044 // No need to rotate if nothing has been written.
45 if (header_written_) {
Austin Schuh58646e22021-08-23 23:51:46 -070046 VLOG(1) << "Rotated " << filename();
Austin Schuhe46492f2021-07-31 19:49:41 -070047 ++parts_index_;
48 reopen_(this);
49 header_written_ = false;
50 QueueHeader(MakeHeader());
51 }
Austin Schuh572924a2021-07-30 22:32:12 -070052}
53
Austin Schuh5e14d842022-01-21 12:02:15 -080054void NewDataWriter::Reboot(const UUID &source_node_boot_uuid) {
Austin Schuh572924a2021-07-30 22:32:12 -070055 parts_uuid_ = UUID::Random();
56 ++parts_index_;
57 reopen_(this);
58 header_written_ = false;
Austin Schuh5e14d842022-01-21 12:02:15 -080059 for (State &state : state_) {
60 state.boot_uuid = UUID::Zero();
61 state.oldest_remote_monotonic_timestamp = monotonic_clock::max_time;
62 state.oldest_local_monotonic_timestamp = monotonic_clock::max_time;
63 state.oldest_remote_unreliable_monotonic_timestamp =
64 monotonic_clock::max_time;
65 state.oldest_local_unreliable_monotonic_timestamp =
66 monotonic_clock::max_time;
Austin Schuhbfe6c572022-01-27 20:48:20 -080067 state.oldest_remote_reliable_monotonic_timestamp =
68 monotonic_clock::max_time;
Austin Schuhf5f99f32022-02-07 20:05:37 -080069 state.oldest_local_reliable_monotonic_timestamp = monotonic_clock::max_time;
70 state.oldest_logger_remote_unreliable_monotonic_timestamp =
71 monotonic_clock::max_time;
72 state.oldest_logger_local_unreliable_monotonic_timestamp =
Austin Schuhbfe6c572022-01-27 20:48:20 -080073 monotonic_clock::max_time;
Austin Schuh5e14d842022-01-21 12:02:15 -080074 }
75
76 state_[node_index_].boot_uuid = source_node_boot_uuid;
77
78 VLOG(1) << "Rebooted " << filename();
79}
80
81void NewDataWriter::UpdateBoot(const UUID &source_node_boot_uuid) {
82 if (state_[node_index_].boot_uuid != source_node_boot_uuid) {
83 state_[node_index_].boot_uuid = source_node_boot_uuid;
84 if (header_written_) {
85 Reboot(source_node_boot_uuid);
86 }
87 }
Austin Schuh572924a2021-07-30 22:32:12 -070088}
89
Austin Schuh72211ae2021-08-05 14:02:30 -070090void NewDataWriter::UpdateRemote(
91 const size_t remote_node_index, const UUID &remote_node_boot_uuid,
92 const monotonic_clock::time_point monotonic_remote_time,
Austin Schuhf5f99f32022-02-07 20:05:37 -080093 const monotonic_clock::time_point monotonic_event_time, const bool reliable,
94 monotonic_clock::time_point monotonic_timestamp_time) {
Austin Schuh58646e22021-08-23 23:51:46 -070095 // Trigger rotation if anything in the header changes.
Austin Schuh72211ae2021-08-05 14:02:30 -070096 bool rotate = false;
97 CHECK_LT(remote_node_index, state_.size());
98 State &state = state_[remote_node_index];
Austin Schuh58646e22021-08-23 23:51:46 -070099
100 // Did the remote boot UUID change?
Austin Schuh72211ae2021-08-05 14:02:30 -0700101 if (state.boot_uuid != remote_node_boot_uuid) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700102 VLOG(1) << filename() << " Remote " << remote_node_index << " updated to "
Austin Schuh72211ae2021-08-05 14:02:30 -0700103 << remote_node_boot_uuid << " from " << state.boot_uuid;
104 state.boot_uuid = remote_node_boot_uuid;
105 state.oldest_remote_monotonic_timestamp = monotonic_clock::max_time;
106 state.oldest_local_monotonic_timestamp = monotonic_clock::max_time;
107 state.oldest_remote_unreliable_monotonic_timestamp =
108 monotonic_clock::max_time;
109 state.oldest_local_unreliable_monotonic_timestamp =
110 monotonic_clock::max_time;
Austin Schuhbfe6c572022-01-27 20:48:20 -0800111 state.oldest_remote_reliable_monotonic_timestamp =
112 monotonic_clock::max_time;
Austin Schuhf5f99f32022-02-07 20:05:37 -0800113 state.oldest_local_reliable_monotonic_timestamp = monotonic_clock::max_time;
114 state.oldest_logger_remote_unreliable_monotonic_timestamp =
115 monotonic_clock::max_time;
116 state.oldest_logger_local_unreliable_monotonic_timestamp =
Austin Schuhbfe6c572022-01-27 20:48:20 -0800117 monotonic_clock::max_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700118 rotate = true;
119 }
120
Austin Schuh58646e22021-08-23 23:51:46 -0700121 // Did the unreliable timestamps change?
Austin Schuh72211ae2021-08-05 14:02:30 -0700122 if (!reliable) {
123 if (state.oldest_remote_unreliable_monotonic_timestamp >
124 monotonic_remote_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700125 VLOG(1) << filename() << " Remote " << remote_node_index
126 << " oldest_remote_unreliable_monotonic_timestamp updated from "
127 << state.oldest_remote_unreliable_monotonic_timestamp << " to "
128 << monotonic_remote_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700129 state.oldest_remote_unreliable_monotonic_timestamp =
130 monotonic_remote_time;
131 state.oldest_local_unreliable_monotonic_timestamp = monotonic_event_time;
132 rotate = true;
133 }
Austin Schuhbfe6c572022-01-27 20:48:20 -0800134 } else {
135 if (state.oldest_remote_reliable_monotonic_timestamp >
136 monotonic_remote_time) {
137 VLOG(1) << filename() << " Remote " << remote_node_index
138 << " oldest_remote_reliable_monotonic_timestamp updated from "
139 << state.oldest_remote_reliable_monotonic_timestamp << " to "
140 << monotonic_remote_time;
141 state.oldest_remote_reliable_monotonic_timestamp = monotonic_remote_time;
142 state.oldest_local_reliable_monotonic_timestamp = monotonic_event_time;
143 rotate = true;
144 }
Austin Schuh72211ae2021-08-05 14:02:30 -0700145 }
146
Austin Schuhf5f99f32022-02-07 20:05:37 -0800147 // Track the logger timestamps too.
148 if (monotonic_timestamp_time != monotonic_clock::min_time) {
149 State &logger_state = state_[node_index_];
150 CHECK_EQ(remote_node_index, logger_node_index_);
151 if (monotonic_event_time <
152 logger_state.oldest_logger_remote_unreliable_monotonic_timestamp) {
153 VLOG(1)
154 << filename() << " Remote " << node_index_
155 << " oldest_logger_remote_unreliable_monotonic_timestamp updated "
156 "from "
157 << logger_state.oldest_logger_remote_unreliable_monotonic_timestamp
158 << " to " << monotonic_event_time;
159 logger_state.oldest_logger_remote_unreliable_monotonic_timestamp =
160 monotonic_event_time;
161 logger_state.oldest_logger_local_unreliable_monotonic_timestamp =
162 monotonic_timestamp_time;
163
164 rotate = true;
165 }
166 }
167
Austin Schuh58646e22021-08-23 23:51:46 -0700168 // Did any of the timestamps change?
Austin Schuh72211ae2021-08-05 14:02:30 -0700169 if (state.oldest_remote_monotonic_timestamp > monotonic_remote_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700170 VLOG(1) << filename() << " Remote " << remote_node_index
171 << " oldest_remote_monotonic_timestamp updated from "
172 << state.oldest_remote_monotonic_timestamp << " to "
173 << monotonic_remote_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700174 state.oldest_remote_monotonic_timestamp = monotonic_remote_time;
175 state.oldest_local_monotonic_timestamp = monotonic_event_time;
176 rotate = true;
177 }
178
179 if (rotate) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700180 Rotate();
181 }
182}
183
Austin Schuh48d10d62022-10-16 22:19:23 -0700184void NewDataWriter::CopyMessage(DataEncoder::Copier *coppier,
185 const UUID &source_node_boot_uuid,
186 aos::monotonic_clock::time_point now) {
Austin Schuh58646e22021-08-23 23:51:46 -0700187 // Trigger a reboot if we detect the boot UUID change.
Austin Schuh5e14d842022-01-21 12:02:15 -0800188 UpdateBoot(source_node_boot_uuid);
Austin Schuh572924a2021-07-30 22:32:12 -0700189
Austin Schuh5e14d842022-01-21 12:02:15 -0800190 if (!header_written_) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700191 QueueHeader(MakeHeader());
Austin Schuh572924a2021-07-30 22:32:12 -0700192 }
Austin Schuh58646e22021-08-23 23:51:46 -0700193
194 // If the start time has changed for this node, trigger a rotation.
195 if (log_namer_->monotonic_start_time(node_index_, source_node_boot_uuid) !=
Austin Schuh5e14d842022-01-21 12:02:15 -0800196 monotonic_start_time_) {
Austin Schuh58646e22021-08-23 23:51:46 -0700197 CHECK(header_written_);
198 Rotate();
199 }
200
201 CHECK_EQ(log_namer_->monotonic_start_time(node_index_, source_node_boot_uuid),
202 monotonic_start_time_);
Austin Schuh72211ae2021-08-05 14:02:30 -0700203 CHECK_EQ(state_[node_index_].boot_uuid, source_node_boot_uuid);
milind-ua50344f2021-08-25 18:22:20 -0700204 CHECK(writer);
Austin Schuh572924a2021-07-30 22:32:12 -0700205 CHECK(header_written_) << ": Attempting to write message before header to "
206 << writer->filename();
Austin Schuh48d10d62022-10-16 22:19:23 -0700207 writer->CopyMessage(coppier, now);
Austin Schuh572924a2021-07-30 22:32:12 -0700208}
209
Austin Schuhe46492f2021-07-31 19:49:41 -0700210aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader>
211NewDataWriter::MakeHeader() {
212 const size_t logger_node_index = log_namer_->logger_node_index();
213 const UUID &logger_node_boot_uuid = log_namer_->logger_node_boot_uuid();
Austin Schuh72211ae2021-08-05 14:02:30 -0700214 if (state_[logger_node_index].boot_uuid == UUID::Zero()) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700215 VLOG(1) << filename() << " Logger node is " << logger_node_index
216 << " and uuid is " << logger_node_boot_uuid;
Austin Schuh72211ae2021-08-05 14:02:30 -0700217 state_[logger_node_index].boot_uuid = logger_node_boot_uuid;
Austin Schuhe46492f2021-07-31 19:49:41 -0700218 } else {
Austin Schuh72211ae2021-08-05 14:02:30 -0700219 CHECK_EQ(state_[logger_node_index].boot_uuid, logger_node_boot_uuid);
Austin Schuhe46492f2021-07-31 19:49:41 -0700220 }
Austin Schuh72211ae2021-08-05 14:02:30 -0700221 return log_namer_->MakeHeader(node_index_, state_, parts_uuid(),
Austin Schuhe46492f2021-07-31 19:49:41 -0700222 parts_index_);
223}
224
Austin Schuh572924a2021-07-30 22:32:12 -0700225void NewDataWriter::QueueHeader(
226 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> &&header) {
227 CHECK(!header_written_) << ": Attempting to write duplicate header to "
228 << writer->filename();
229 CHECK(header.message().has_source_node_boot_uuid());
Austin Schuh72211ae2021-08-05 14:02:30 -0700230 CHECK_EQ(state_[node_index_].boot_uuid,
Austin Schuhe46492f2021-07-31 19:49:41 -0700231 UUID::FromString(header.message().source_node_boot_uuid()));
Austin Schuh510dc622021-08-06 18:47:30 -0700232 if (!writer) {
Austin Schuh48d10d62022-10-16 22:19:23 -0700233 // Since we haven't opened the first time, it's still not too late to update
234 // the max message size. Make sure the header fits.
235 //
236 // This won't work well on reboots, but the structure of the header is fixed
237 // by that point in time, so it's size is fixed too.
238 //
239 // Most of the time, the minimum buffer size inside the encoder of around
240 // 128k will make this a non-issue.
241 UpdateMaxMessageSize(header.span().size());
242
Austin Schuh510dc622021-08-06 18:47:30 -0700243 reopen_(this);
244 }
245
Austin Schuh58646e22021-08-23 23:51:46 -0700246 VLOG(1) << "Writing to " << filename() << " "
247 << aos::FlatbufferToJson(
248 header, {.multi_line = false, .max_vector_size = 100});
249
Austin Schuh510dc622021-08-06 18:47:30 -0700250 CHECK(writer);
Austin Schuh7ef11a42023-02-04 17:15:12 -0800251 DataEncoder::SpanCopier coppier(header.span());
252 writer->CopyMessage(&coppier, aos::monotonic_clock::now());
Austin Schuh572924a2021-07-30 22:32:12 -0700253 header_written_ = true;
Austin Schuh58646e22021-08-23 23:51:46 -0700254 monotonic_start_time_ = log_namer_->monotonic_start_time(
255 node_index_, state_[node_index_].boot_uuid);
Austin Schuh572924a2021-07-30 22:32:12 -0700256}
257
258void NewDataWriter::Close() {
259 CHECK(writer);
260 close_(this);
261 writer.reset();
262 header_written_ = false;
263}
264
Austin Schuh58646e22021-08-23 23:51:46 -0700265LogNamer::NodeState *LogNamer::GetNodeState(size_t node_index,
266 const UUID &boot_uuid) {
267 auto it = node_states_.find(std::make_pair(node_index, boot_uuid));
268 if (it == node_states_.end()) {
269 it =
270 node_states_.emplace(std::make_pair(node_index, boot_uuid), NodeState())
271 .first;
272 }
273 return &it->second;
274}
275
Austin Schuh73340842021-07-30 22:32:06 -0700276aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> LogNamer::MakeHeader(
Austin Schuh72211ae2021-08-05 14:02:30 -0700277 size_t node_index, const std::vector<NewDataWriter::State> &state,
Austin Schuh58646e22021-08-23 23:51:46 -0700278 const UUID &parts_uuid, int parts_index) {
Austin Schuh72211ae2021-08-05 14:02:30 -0700279 const UUID &source_node_boot_uuid = state[node_index].boot_uuid;
Austin Schuh73340842021-07-30 22:32:06 -0700280 const Node *const source_node =
281 configuration::GetNode(configuration_, node_index);
Austin Schuhfa712682022-05-11 16:43:42 -0700282 CHECK_EQ(LogFileHeader::MiniReflectTypeTable()->num_elems, 34u);
Austin Schuh73340842021-07-30 22:32:06 -0700283 flatbuffers::FlatBufferBuilder fbb;
284 fbb.ForceDefaults(true);
285
286 flatbuffers::Offset<flatbuffers::String> config_sha256_offset;
287 flatbuffers::Offset<aos::Configuration> configuration_offset;
288 if (header_.message().has_configuration()) {
289 CHECK(!header_.message().has_configuration_sha256());
290 configuration_offset =
291 CopyFlatBuffer(header_.message().configuration(), &fbb);
292 } else {
293 CHECK(!header_.message().has_configuration());
294 CHECK(header_.message().has_configuration_sha256());
295 config_sha256_offset = fbb.CreateString(
296 header_.message().configuration_sha256()->string_view());
297 }
298
299 CHECK(header_.message().has_name());
300 const flatbuffers::Offset<flatbuffers::String> name_offset =
301 fbb.CreateString(header_.message().name()->string_view());
Austin Schuhfa712682022-05-11 16:43:42 -0700302 const flatbuffers::Offset<flatbuffers::String> logger_sha1_offset =
303 header_.message().has_logger_sha1()
304 ? fbb.CreateString(header_.message().logger_sha1()->string_view())
305 : 0;
306 const flatbuffers::Offset<flatbuffers::String> logger_version_offset =
307 header_.message().has_logger_version()
308 ? fbb.CreateString(header_.message().logger_version()->string_view())
309 : 0;
Austin Schuh73340842021-07-30 22:32:06 -0700310
311 CHECK(header_.message().has_log_event_uuid());
312 const flatbuffers::Offset<flatbuffers::String> log_event_uuid_offset =
313 fbb.CreateString(header_.message().log_event_uuid()->string_view());
314
315 CHECK(header_.message().has_logger_instance_uuid());
316 const flatbuffers::Offset<flatbuffers::String> logger_instance_uuid_offset =
317 fbb.CreateString(header_.message().logger_instance_uuid()->string_view());
318
319 flatbuffers::Offset<flatbuffers::String> log_start_uuid_offset;
320 if (header_.message().has_log_start_uuid()) {
321 log_start_uuid_offset =
322 fbb.CreateString(header_.message().log_start_uuid()->string_view());
323 }
324
325 CHECK(header_.message().has_logger_node_boot_uuid());
326 const flatbuffers::Offset<flatbuffers::String> logger_node_boot_uuid_offset =
327 fbb.CreateString(
328 header_.message().logger_node_boot_uuid()->string_view());
329
330 CHECK_NE(source_node_boot_uuid, UUID::Zero());
331 const flatbuffers::Offset<flatbuffers::String> source_node_boot_uuid_offset =
332 source_node_boot_uuid.PackString(&fbb);
333
334 const flatbuffers::Offset<flatbuffers::String> parts_uuid_offset =
335 parts_uuid.PackString(&fbb);
336
337 flatbuffers::Offset<Node> node_offset;
338 flatbuffers::Offset<Node> logger_node_offset;
339
340 if (configuration::MultiNode(configuration_)) {
341 node_offset = RecursiveCopyFlatBuffer(source_node, &fbb);
342 logger_node_offset = RecursiveCopyFlatBuffer(node_, &fbb);
343 }
344
Austin Schuhe46492f2021-07-31 19:49:41 -0700345 std::vector<flatbuffers::Offset<flatbuffers::String>> boot_uuid_offsets;
Austin Schuh72211ae2021-08-05 14:02:30 -0700346 boot_uuid_offsets.reserve(state.size());
Austin Schuhe46492f2021-07-31 19:49:41 -0700347
Austin Schuh4db9ec92021-09-22 13:11:12 -0700348 int64_t *unused;
Austin Schuh72211ae2021-08-05 14:02:30 -0700349 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
Austin Schuhf5f99f32022-02-07 20:05:37 -0800350 oldest_remote_monotonic_timestamps_offset =
351 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700352
Austin Schuh72211ae2021-08-05 14:02:30 -0700353 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
Austin Schuhf5f99f32022-02-07 20:05:37 -0800354 oldest_local_monotonic_timestamps_offset =
355 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700356
Austin Schuh72211ae2021-08-05 14:02:30 -0700357 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
358 oldest_remote_unreliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800359 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700360
Austin Schuh72211ae2021-08-05 14:02:30 -0700361 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
362 oldest_local_unreliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800363 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700364
Austin Schuhbfe6c572022-01-27 20:48:20 -0800365 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
366 oldest_remote_reliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800367 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800368
369 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
370 oldest_local_reliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800371 fbb.CreateUninitializedVector(state.size(), &unused);
372
373 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
374 oldest_logger_remote_unreliable_monotonic_timestamps_offset =
375 fbb.CreateUninitializedVector(state.size(), &unused);
376
377 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
378 oldest_logger_local_unreliable_monotonic_timestamps_offset =
379 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800380
Austin Schuh72211ae2021-08-05 14:02:30 -0700381 for (size_t i = 0; i < state.size(); ++i) {
Austin Schuh4db9ec92021-09-22 13:11:12 -0700382 if (state[i].boot_uuid != UUID::Zero()) {
383 boot_uuid_offsets.emplace_back(state[i].boot_uuid.PackString(&fbb));
384 } else {
385 boot_uuid_offsets.emplace_back(fbb.CreateString(""));
386 }
Austin Schuh5ae8f4a2021-09-11 19:09:50 -0700387 if (state[i].boot_uuid == UUID::Zero()) {
388 CHECK_EQ(state[i].oldest_remote_monotonic_timestamp,
389 monotonic_clock::max_time);
390 CHECK_EQ(state[i].oldest_local_monotonic_timestamp,
391 monotonic_clock::max_time);
392 CHECK_EQ(state[i].oldest_remote_unreliable_monotonic_timestamp,
393 monotonic_clock::max_time);
394 CHECK_EQ(state[i].oldest_local_unreliable_monotonic_timestamp,
395 monotonic_clock::max_time);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800396 CHECK_EQ(state[i].oldest_remote_reliable_monotonic_timestamp,
397 monotonic_clock::max_time);
398 CHECK_EQ(state[i].oldest_local_reliable_monotonic_timestamp,
399 monotonic_clock::max_time);
Austin Schuhf5f99f32022-02-07 20:05:37 -0800400 CHECK_EQ(state[i].oldest_logger_remote_unreliable_monotonic_timestamp,
401 monotonic_clock::max_time);
402 CHECK_EQ(state[i].oldest_logger_local_unreliable_monotonic_timestamp,
403 monotonic_clock::max_time);
Austin Schuh5ae8f4a2021-09-11 19:09:50 -0700404 }
405
Austin Schuh4db9ec92021-09-22 13:11:12 -0700406 flatbuffers::GetMutableTemporaryPointer(
407 fbb, oldest_remote_monotonic_timestamps_offset)
408 ->Mutate(i, state[i]
409 .oldest_remote_monotonic_timestamp.time_since_epoch()
410 .count());
411 flatbuffers::GetMutableTemporaryPointer(
412 fbb, oldest_local_monotonic_timestamps_offset)
413 ->Mutate(i, state[i]
414 .oldest_local_monotonic_timestamp.time_since_epoch()
415 .count());
416 flatbuffers::GetMutableTemporaryPointer(
417 fbb, oldest_remote_unreliable_monotonic_timestamps_offset)
418 ->Mutate(i, state[i]
Austin Schuhbfe6c572022-01-27 20:48:20 -0800419 .oldest_remote_unreliable_monotonic_timestamp
420 .time_since_epoch()
Austin Schuh4db9ec92021-09-22 13:11:12 -0700421 .count());
422 flatbuffers::GetMutableTemporaryPointer(
423 fbb, oldest_local_unreliable_monotonic_timestamps_offset)
424 ->Mutate(i, state[i]
Austin Schuhbfe6c572022-01-27 20:48:20 -0800425 .oldest_local_unreliable_monotonic_timestamp
426 .time_since_epoch()
Austin Schuh4db9ec92021-09-22 13:11:12 -0700427 .count());
Austin Schuhbfe6c572022-01-27 20:48:20 -0800428
429 flatbuffers::GetMutableTemporaryPointer(
430 fbb, oldest_remote_reliable_monotonic_timestamps_offset)
431 ->Mutate(i, state[i]
432 .oldest_remote_reliable_monotonic_timestamp
433 .time_since_epoch()
434 .count());
435 flatbuffers::GetMutableTemporaryPointer(
436 fbb, oldest_local_reliable_monotonic_timestamps_offset)
437 ->Mutate(
438 i, state[i]
439 .oldest_local_reliable_monotonic_timestamp.time_since_epoch()
440 .count());
Austin Schuhf5f99f32022-02-07 20:05:37 -0800441
442 flatbuffers::GetMutableTemporaryPointer(
443 fbb, oldest_logger_remote_unreliable_monotonic_timestamps_offset)
444 ->Mutate(i, state[i]
445 .oldest_logger_remote_unreliable_monotonic_timestamp
446 .time_since_epoch()
447 .count());
448 flatbuffers::GetMutableTemporaryPointer(
449 fbb, oldest_logger_local_unreliable_monotonic_timestamps_offset)
450 ->Mutate(i, state[i]
451 .oldest_logger_local_unreliable_monotonic_timestamp
452 .time_since_epoch()
453 .count());
Austin Schuh72211ae2021-08-05 14:02:30 -0700454 }
455
Austin Schuh4db9ec92021-09-22 13:11:12 -0700456 flatbuffers::Offset<
457 flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
458 boot_uuids_offset = fbb.CreateVector(boot_uuid_offsets);
459
Austin Schuh73340842021-07-30 22:32:06 -0700460 aos::logger::LogFileHeader::Builder log_file_header_builder(fbb);
461
462 log_file_header_builder.add_name(name_offset);
Austin Schuhfa712682022-05-11 16:43:42 -0700463 if (!logger_sha1_offset.IsNull()) {
464 log_file_header_builder.add_logger_sha1(logger_sha1_offset);
465 }
466 if (!logger_version_offset.IsNull()) {
467 log_file_header_builder.add_logger_version(logger_version_offset);
468 }
Austin Schuh73340842021-07-30 22:32:06 -0700469
470 // Only add the node if we are running in a multinode configuration.
471 if (!logger_node_offset.IsNull()) {
472 log_file_header_builder.add_node(node_offset);
473 log_file_header_builder.add_logger_node(logger_node_offset);
474 }
475
476 if (!configuration_offset.IsNull()) {
477 log_file_header_builder.add_configuration(configuration_offset);
478 }
479 log_file_header_builder.add_max_out_of_order_duration(
480 header_.message().max_out_of_order_duration());
481
Austin Schuh58646e22021-08-23 23:51:46 -0700482 NodeState *node_state = GetNodeState(node_index, source_node_boot_uuid);
Austin Schuh73340842021-07-30 22:32:06 -0700483 log_file_header_builder.add_monotonic_start_time(
484 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700485 node_state->monotonic_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700486 .count());
487 if (source_node == node_) {
488 log_file_header_builder.add_realtime_start_time(
489 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700490 node_state->realtime_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700491 .count());
492 } else {
493 // Fill out the legacy start times. Since these were implemented to never
494 // change on reboot, they aren't very helpful in tracking what happened.
495 log_file_header_builder.add_logger_monotonic_start_time(
496 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700497 node_state->logger_monotonic_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700498 .count());
499 log_file_header_builder.add_logger_realtime_start_time(
500 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700501 node_state->logger_realtime_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700502 .count());
503 }
504
505 // TODO(austin): Add more useful times. When was this part started? What do
506 // we know about both the logger and remote then?
507
508 log_file_header_builder.add_log_event_uuid(log_event_uuid_offset);
509 log_file_header_builder.add_logger_instance_uuid(logger_instance_uuid_offset);
510 if (!log_start_uuid_offset.IsNull()) {
511 log_file_header_builder.add_log_start_uuid(log_start_uuid_offset);
512 }
513 log_file_header_builder.add_logger_node_boot_uuid(
514 logger_node_boot_uuid_offset);
515 log_file_header_builder.add_source_node_boot_uuid(
516 source_node_boot_uuid_offset);
517
518 log_file_header_builder.add_parts_uuid(parts_uuid_offset);
519 log_file_header_builder.add_parts_index(parts_index);
520
521 if (!config_sha256_offset.IsNull()) {
522 log_file_header_builder.add_configuration_sha256(config_sha256_offset);
523 }
524
Austin Schuhe46492f2021-07-31 19:49:41 -0700525 log_file_header_builder.add_boot_uuids(boot_uuids_offset);
Austin Schuha499cea2021-07-31 19:49:53 -0700526 log_file_header_builder.add_logger_part_monotonic_start_time(
527 std::chrono::duration_cast<std::chrono::nanoseconds>(
528 event_loop_->monotonic_now().time_since_epoch())
529 .count());
530 log_file_header_builder.add_logger_part_realtime_start_time(
531 std::chrono::duration_cast<std::chrono::nanoseconds>(
532 event_loop_->realtime_now().time_since_epoch())
533 .count());
Austin Schuh72211ae2021-08-05 14:02:30 -0700534 log_file_header_builder.add_oldest_remote_monotonic_timestamps(
535 oldest_remote_monotonic_timestamps_offset);
536 log_file_header_builder.add_oldest_local_monotonic_timestamps(
537 oldest_local_monotonic_timestamps_offset);
538 log_file_header_builder.add_oldest_remote_unreliable_monotonic_timestamps(
539 oldest_remote_unreliable_monotonic_timestamps_offset);
540 log_file_header_builder.add_oldest_local_unreliable_monotonic_timestamps(
541 oldest_local_unreliable_monotonic_timestamps_offset);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800542 log_file_header_builder.add_oldest_remote_reliable_monotonic_timestamps(
543 oldest_remote_reliable_monotonic_timestamps_offset);
544 log_file_header_builder.add_oldest_local_reliable_monotonic_timestamps(
545 oldest_local_reliable_monotonic_timestamps_offset);
Austin Schuhf5f99f32022-02-07 20:05:37 -0800546 log_file_header_builder
547 .add_oldest_logger_remote_unreliable_monotonic_timestamps(
548 oldest_logger_remote_unreliable_monotonic_timestamps_offset);
549 log_file_header_builder
550 .add_oldest_logger_local_unreliable_monotonic_timestamps(
551 oldest_logger_local_unreliable_monotonic_timestamps_offset);
Austin Schuh73340842021-07-30 22:32:06 -0700552 fbb.FinishSizePrefixed(log_file_header_builder.Finish());
553 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> result(
554 fbb.Release());
555
556 CHECK(result.Verify()) << ": Built a corrupted header.";
557
558 return result;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700559}
560
Austin Schuhcb5601b2020-09-10 15:29:59 -0700561MultiNodeLogNamer::MultiNodeLogNamer(std::string_view base_name,
Austin Schuha499cea2021-07-31 19:49:53 -0700562 EventLoop *event_loop)
Austin Schuh5b728b72021-06-16 14:57:15 -0700563 : MultiNodeLogNamer(base_name, event_loop->configuration(), event_loop,
564 event_loop->node()) {}
565
566MultiNodeLogNamer::MultiNodeLogNamer(std::string_view base_name,
567 const Configuration *configuration,
568 EventLoop *event_loop, const Node *node)
569 : LogNamer(configuration, event_loop, node),
570 base_name_(base_name),
571 old_base_name_() {}
Austin Schuhcb5601b2020-09-10 15:29:59 -0700572
Brian Silverman48deab12020-09-30 18:39:28 -0700573MultiNodeLogNamer::~MultiNodeLogNamer() {
574 if (!ran_out_of_space_) {
575 // This handles renaming temporary files etc.
576 Close();
577 }
578}
579
Austin Schuh572924a2021-07-30 22:32:12 -0700580void MultiNodeLogNamer::Rotate(const Node *node) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700581 if (node == this->node()) {
Austin Schuhb8bca732021-07-30 22:32:00 -0700582 if (data_writer_) {
Austin Schuh572924a2021-07-30 22:32:12 -0700583 data_writer_->Rotate();
Brian Silvermancb805822020-10-06 17:43:35 -0700584 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700585 } else {
Austin Schuhb8bca732021-07-30 22:32:00 -0700586 for (std::pair<const Channel *const, NewDataWriter> &data_writer :
Austin Schuhcb5601b2020-09-10 15:29:59 -0700587 data_writers_) {
Austin Schuh572924a2021-07-30 22:32:12 -0700588 if (node == data_writer.second.node()) {
589 data_writer.second.Rotate();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700590 }
591 }
592 }
593}
594
Austin Schuh8c399962020-12-25 21:51:45 -0800595void MultiNodeLogNamer::WriteConfiguration(
596 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
597 std::string_view config_sha256) {
598 if (ran_out_of_space_) {
599 return;
600 }
601
602 const std::string_view separator = base_name_.back() == '/' ? "" : "_";
603 const std::string filename = absl::StrCat(
604 base_name_, separator, config_sha256, ".bfbs", extension_, temp_suffix_);
605
606 std::unique_ptr<DetachedBufferWriter> writer =
Austin Schuh48d10d62022-10-16 22:19:23 -0700607 std::make_unique<DetachedBufferWriter>(
608 filename, encoder_factory_(header->span().size()));
Austin Schuh8c399962020-12-25 21:51:45 -0800609
Austin Schuh7ef11a42023-02-04 17:15:12 -0800610 DataEncoder::SpanCopier coppier(header->span());
611 writer->CopyMessage(&coppier, aos::monotonic_clock::now());
Austin Schuh8c399962020-12-25 21:51:45 -0800612
613 if (!writer->ran_out_of_space()) {
Austin Schuh5b728b72021-06-16 14:57:15 -0700614 all_filenames_.emplace_back(
615 absl::StrCat(config_sha256, ".bfbs", extension_));
Austin Schuh8c399962020-12-25 21:51:45 -0800616 }
617 CloseWriter(&writer);
618}
619
Austin Schuhb8bca732021-07-30 22:32:00 -0700620NewDataWriter *MultiNodeLogNamer::MakeWriter(const Channel *channel) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700621 // See if we can read the data on this node at all.
622 const bool is_readable =
623 configuration::ChannelIsReadableOnNode(channel, this->node());
624 if (!is_readable) {
625 return nullptr;
626 }
627
628 // Then, see if we are supposed to log the data here.
629 const bool log_message =
630 configuration::ChannelMessageIsLoggedOnNode(channel, this->node());
631
632 if (!log_message) {
633 return nullptr;
634 }
635
636 // Now, sort out if this is data generated on this node, or not. It is
637 // generated if it is sendable on this node.
638 if (configuration::ChannelIsSendableOnNode(channel, this->node())) {
Austin Schuhb8bca732021-07-30 22:32:00 -0700639 if (!data_writer_) {
Austin Schuh48d10d62022-10-16 22:19:23 -0700640 MakeDataWriter();
Brian Silvermancb805822020-10-06 17:43:35 -0700641 }
Austin Schuh48d10d62022-10-16 22:19:23 -0700642 data_writer_->UpdateMaxMessageSize(PackMessageSize(
643 LogType::kLogRemoteMessage, channel->max_size()));
Austin Schuhb8bca732021-07-30 22:32:00 -0700644 return data_writer_.get();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700645 }
646
647 // Ok, we have data that is being forwarded to us that we are supposed to
648 // log. It needs to be logged with send timestamps, but be sorted enough
649 // to be able to be processed.
650 CHECK(data_writers_.find(channel) == data_writers_.end());
651
652 // Track that this node is being logged.
653 const Node *source_node = configuration::GetNode(
654 configuration_, channel->source_node()->string_view());
655
656 if (std::find(nodes_.begin(), nodes_.end(), source_node) == nodes_.end()) {
657 nodes_.emplace_back(source_node);
658 }
659
Austin Schuhf5f99f32022-02-07 20:05:37 -0800660 NewDataWriter data_writer(
661 this, source_node, node_,
662 [this, channel](NewDataWriter *data_writer) {
663 OpenWriter(channel, data_writer);
664 },
Austin Schuh48d10d62022-10-16 22:19:23 -0700665 [this](NewDataWriter *data_writer) { CloseWriter(&data_writer->writer); },
666 PackMessageSize(LogType::kLogRemoteMessage, channel->max_size()));
Austin Schuhb8bca732021-07-30 22:32:00 -0700667 return &(
668 data_writers_.emplace(channel, std::move(data_writer)).first->second);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700669}
670
Austin Schuhb8bca732021-07-30 22:32:00 -0700671NewDataWriter *MultiNodeLogNamer::MakeForwardedTimestampWriter(
Austin Schuhcb5601b2020-09-10 15:29:59 -0700672 const Channel *channel, const Node *node) {
673 // See if we can read the data on this node at all.
674 const bool is_readable =
675 configuration::ChannelIsReadableOnNode(channel, this->node());
676 CHECK(is_readable) << ": " << configuration::CleanedChannelToString(channel);
677
678 CHECK(data_writers_.find(channel) == data_writers_.end());
679
680 if (std::find(nodes_.begin(), nodes_.end(), node) == nodes_.end()) {
681 nodes_.emplace_back(node);
682 }
683
Austin Schuhf5f99f32022-02-07 20:05:37 -0800684 NewDataWriter data_writer(
685 this, configuration::GetNode(configuration_, node), node_,
686 [this, channel](NewDataWriter *data_writer) {
687 OpenForwardedTimestampWriter(channel, data_writer);
688 },
Austin Schuh48d10d62022-10-16 22:19:23 -0700689 [this](NewDataWriter *data_writer) { CloseWriter(&data_writer->writer); },
690 PackRemoteMessageSize());
Austin Schuhb8bca732021-07-30 22:32:00 -0700691 return &(
692 data_writers_.emplace(channel, std::move(data_writer)).first->second);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700693}
694
Austin Schuhb8bca732021-07-30 22:32:00 -0700695NewDataWriter *MultiNodeLogNamer::MakeTimestampWriter(const Channel *channel) {
Brian Silverman0465fcf2020-09-24 00:29:18 -0700696 bool log_delivery_times = false;
697 if (this->node() != nullptr) {
698 log_delivery_times = configuration::ConnectionDeliveryTimeIsLoggedOnNode(
699 channel, this->node(), this->node());
700 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700701 if (!log_delivery_times) {
702 return nullptr;
703 }
704
Austin Schuhb8bca732021-07-30 22:32:00 -0700705 if (!data_writer_) {
Austin Schuh48d10d62022-10-16 22:19:23 -0700706 MakeDataWriter();
Brian Silvermancb805822020-10-06 17:43:35 -0700707 }
Austin Schuh48d10d62022-10-16 22:19:23 -0700708 data_writer_->UpdateMaxMessageSize(
709 PackMessageSize(LogType::kLogDeliveryTimeOnly, 0));
Austin Schuhb8bca732021-07-30 22:32:00 -0700710 return data_writer_.get();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700711}
712
Brian Silverman0465fcf2020-09-24 00:29:18 -0700713void MultiNodeLogNamer::Close() {
Austin Schuhb8bca732021-07-30 22:32:00 -0700714 data_writers_.clear();
715 data_writer_.reset();
Brian Silvermancb805822020-10-06 17:43:35 -0700716}
717
718void MultiNodeLogNamer::ResetStatistics() {
Austin Schuhb8bca732021-07-30 22:32:00 -0700719 for (std::pair<const Channel *const, NewDataWriter> &data_writer :
Brian Silvermancb805822020-10-06 17:43:35 -0700720 data_writers_) {
Austin Schuhad0cfc32020-12-21 12:34:26 -0800721 if (!data_writer.second.writer) continue;
Brian Silvermancb805822020-10-06 17:43:35 -0700722 data_writer.second.writer->ResetStatistics();
Brian Silverman0465fcf2020-09-24 00:29:18 -0700723 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700724 if (data_writer_) {
725 data_writer_->writer->ResetStatistics();
Brian Silvermancb805822020-10-06 17:43:35 -0700726 }
727 max_write_time_ = std::chrono::nanoseconds::zero();
728 max_write_time_bytes_ = -1;
729 max_write_time_messages_ = -1;
730 total_write_time_ = std::chrono::nanoseconds::zero();
731 total_write_count_ = 0;
732 total_write_messages_ = 0;
733 total_write_bytes_ = 0;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700734}
735
Austin Schuhb8bca732021-07-30 22:32:00 -0700736void MultiNodeLogNamer::OpenForwardedTimestampWriter(
737 const Channel *channel, NewDataWriter *data_writer) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700738 std::string filename =
Austin Schuhe715eae2020-10-10 15:39:30 -0700739 absl::StrCat("timestamps", channel->name()->string_view(), "/",
Brian Silvermana621f522020-09-30 16:52:43 -0700740 channel->type()->string_view(), ".part",
Austin Schuh572924a2021-07-30 22:32:12 -0700741 data_writer->parts_index(), ".bfbs", extension_);
Austin Schuh48d10d62022-10-16 22:19:23 -0700742 CreateBufferWriter(filename, data_writer->max_message_size(),
743 &data_writer->writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700744}
745
746void MultiNodeLogNamer::OpenWriter(const Channel *channel,
Austin Schuhb8bca732021-07-30 22:32:00 -0700747 NewDataWriter *data_writer) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700748 const std::string filename = absl::StrCat(
Austin Schuhe715eae2020-10-10 15:39:30 -0700749 CHECK_NOTNULL(channel->source_node())->string_view(), "_data",
Brian Silvermana621f522020-09-30 16:52:43 -0700750 channel->name()->string_view(), "/", channel->type()->string_view(),
Austin Schuh572924a2021-07-30 22:32:12 -0700751 ".part", data_writer->parts_index(), ".bfbs", extension_);
Austin Schuh48d10d62022-10-16 22:19:23 -0700752 CreateBufferWriter(filename, data_writer->max_message_size(),
753 &data_writer->writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700754}
755
Austin Schuh48d10d62022-10-16 22:19:23 -0700756void MultiNodeLogNamer::MakeDataWriter() {
Austin Schuhb8bca732021-07-30 22:32:00 -0700757 if (!data_writer_) {
758 data_writer_ = std::make_unique<NewDataWriter>(
Austin Schuhf5f99f32022-02-07 20:05:37 -0800759 this, node_, node_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700760 [this](NewDataWriter *writer) {
761 std::string name;
762 if (node() != nullptr) {
763 name = absl::StrCat(name, node()->name()->string_view(), "_");
764 }
Austin Schuh572924a2021-07-30 22:32:12 -0700765 absl::StrAppend(&name, "data.part", writer->parts_index(), ".bfbs",
Austin Schuhb8bca732021-07-30 22:32:00 -0700766 extension_);
Austin Schuh48d10d62022-10-16 22:19:23 -0700767 CreateBufferWriter(name, writer->max_message_size(), &writer->writer);
Austin Schuhb8bca732021-07-30 22:32:00 -0700768 },
769 [this](NewDataWriter *data_writer) {
770 CloseWriter(&data_writer->writer);
Austin Schuh48d10d62022-10-16 22:19:23 -0700771 },
772 // Default size is 0 so it will be obvious if something doesn't fix it
773 // afterwards.
774 0);
Brian Silverman7af8c902020-09-29 16:14:04 -0700775 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700776}
777
Brian Silverman0465fcf2020-09-24 00:29:18 -0700778void MultiNodeLogNamer::CreateBufferWriter(
Austin Schuh48d10d62022-10-16 22:19:23 -0700779 std::string_view path, size_t max_message_size,
780 std::unique_ptr<DetachedBufferWriter> *destination) {
Brian Silverman0465fcf2020-09-24 00:29:18 -0700781 if (ran_out_of_space_) {
782 // Refuse to open any new files, which might skip data. Any existing files
783 // are in the same folder, which means they're on the same filesystem, which
784 // means they're probably going to run out of space and get stuck too.
Austin Schuha426f1f2021-03-31 22:27:41 -0700785 if (!destination->get()) {
786 // But avoid leaving a nullptr writer if we're out of space when
787 // attempting to open the first file.
788 *destination = std::make_unique<DetachedBufferWriter>(
789 DetachedBufferWriter::already_out_of_space_t());
790 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700791 return;
792 }
Austin Schuhe715eae2020-10-10 15:39:30 -0700793 const std::string_view separator = base_name_.back() == '/' ? "" : "_";
794 const std::string filename =
795 absl::StrCat(base_name_, separator, path, temp_suffix_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700796 if (!destination->get()) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700797 if (ran_out_of_space_) {
798 *destination = std::make_unique<DetachedBufferWriter>(
799 DetachedBufferWriter::already_out_of_space_t());
800 return;
801 }
Austin Schuh48d10d62022-10-16 22:19:23 -0700802 *destination = std::make_unique<DetachedBufferWriter>(
803 filename, encoder_factory_(max_message_size));
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700804 if (!destination->get()->ran_out_of_space()) {
805 all_filenames_.emplace_back(path);
806 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700807 return;
808 }
Brian Silvermancb805822020-10-06 17:43:35 -0700809
810 CloseWriter(destination);
811 if (ran_out_of_space_) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700812 *destination->get() =
813 DetachedBufferWriter(DetachedBufferWriter::already_out_of_space_t());
Brian Silverman0465fcf2020-09-24 00:29:18 -0700814 return;
815 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700816
Austin Schuh48d10d62022-10-16 22:19:23 -0700817 *destination->get() =
818 DetachedBufferWriter(filename, encoder_factory_(max_message_size));
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700819 if (!destination->get()->ran_out_of_space()) {
820 all_filenames_.emplace_back(path);
821 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700822}
823
Brian Silverman48deab12020-09-30 18:39:28 -0700824void MultiNodeLogNamer::RenameTempFile(DetachedBufferWriter *destination) {
825 if (temp_suffix_.empty()) {
826 return;
827 }
Austin Schuh6bb8a822021-03-31 23:04:39 -0700828 std::string current_filename = std::string(destination->filename());
Brian Silverman48deab12020-09-30 18:39:28 -0700829 CHECK(current_filename.size() > temp_suffix_.size());
Austin Schuh6bb8a822021-03-31 23:04:39 -0700830 std::string final_filename =
Brian Silverman48deab12020-09-30 18:39:28 -0700831 current_filename.substr(0, current_filename.size() - temp_suffix_.size());
Austin Schuh6bb8a822021-03-31 23:04:39 -0700832 int result = rename(current_filename.c_str(), final_filename.c_str());
833
834 // When changing the base name, we rename the log folder while there active
835 // buffer writers. Therefore, the name of that active buffer may still refer
836 // to the old file location rather than the new one. This minimized changes to
837 // existing code.
838 if (result != 0 && errno != ENOSPC && !old_base_name_.empty()) {
839 auto offset = current_filename.find(old_base_name_);
840 if (offset != std::string::npos) {
841 current_filename.replace(offset, old_base_name_.length(), base_name_);
842 }
843 offset = final_filename.find(old_base_name_);
844 if (offset != std::string::npos) {
845 final_filename.replace(offset, old_base_name_.length(), base_name_);
846 }
847 result = rename(current_filename.c_str(), final_filename.c_str());
848 }
849
Brian Silverman48deab12020-09-30 18:39:28 -0700850 if (result != 0) {
851 if (errno == ENOSPC) {
852 ran_out_of_space_ = true;
853 return;
854 } else {
855 PLOG(FATAL) << "Renaming " << current_filename << " to " << final_filename
856 << " failed";
857 }
Austin Schuh6bb8a822021-03-31 23:04:39 -0700858 } else {
859 VLOG(1) << "Renamed " << current_filename << " -> " << final_filename;
Brian Silverman48deab12020-09-30 18:39:28 -0700860 }
861}
862
Brian Silvermancb805822020-10-06 17:43:35 -0700863void MultiNodeLogNamer::CloseWriter(
864 std::unique_ptr<DetachedBufferWriter> *writer_pointer) {
865 DetachedBufferWriter *const writer = writer_pointer->get();
866 if (!writer) {
867 return;
868 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700869 const bool was_open = writer->is_open();
Brian Silvermancb805822020-10-06 17:43:35 -0700870 writer->Close();
871
872 if (writer->max_write_time() > max_write_time_) {
873 max_write_time_ = writer->max_write_time();
874 max_write_time_bytes_ = writer->max_write_time_bytes();
875 max_write_time_messages_ = writer->max_write_time_messages();
876 }
877 total_write_time_ += writer->total_write_time();
878 total_write_count_ += writer->total_write_count();
879 total_write_messages_ += writer->total_write_messages();
880 total_write_bytes_ += writer->total_write_bytes();
881
882 if (writer->ran_out_of_space()) {
883 ran_out_of_space_ = true;
884 writer->acknowledge_out_of_space();
885 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700886 if (was_open) {
887 RenameTempFile(writer);
888 } else {
889 CHECK(access(std::string(writer->filename()).c_str(), F_OK) == -1)
890 << ": File should not exist: " << writer->filename();
891 }
Brian Silvermancb805822020-10-06 17:43:35 -0700892}
893
Austin Schuhcb5601b2020-09-10 15:29:59 -0700894} // namespace logger
895} // namespace aos