blob: 6fd39f856661aa1e003b0ee08799fab664bee078 [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,
23 std::function<void(NewDataWriter *)> close)
24 : node_(node),
25 node_index_(configuration::GetNodeIndex(log_namer->configuration_, node)),
Austin Schuhf5f99f32022-02-07 20:05:37 -080026 logger_node_index_(
27 configuration::GetNodeIndex(log_namer->configuration_, logger_node)),
Austin Schuh572924a2021-07-30 22:32:12 -070028 log_namer_(log_namer),
29 reopen_(std::move(reopen)),
30 close_(std::move(close)) {
Austin Schuh72211ae2021-08-05 14:02:30 -070031 state_.resize(configuration::NodesCount(log_namer->configuration_));
32 CHECK_LT(node_index_, state_.size());
Austin Schuh572924a2021-07-30 22:32:12 -070033}
34
35NewDataWriter::~NewDataWriter() {
36 if (writer) {
37 Close();
38 }
39}
40
41void NewDataWriter::Rotate() {
Austin Schuhe46492f2021-07-31 19:49:41 -070042 // No need to rotate if nothing has been written.
43 if (header_written_) {
Austin Schuh58646e22021-08-23 23:51:46 -070044 VLOG(1) << "Rotated " << filename();
Austin Schuhe46492f2021-07-31 19:49:41 -070045 ++parts_index_;
46 reopen_(this);
47 header_written_ = false;
48 QueueHeader(MakeHeader());
49 }
Austin Schuh572924a2021-07-30 22:32:12 -070050}
51
Austin Schuh5e14d842022-01-21 12:02:15 -080052void NewDataWriter::Reboot(const UUID &source_node_boot_uuid) {
Austin Schuh572924a2021-07-30 22:32:12 -070053 parts_uuid_ = UUID::Random();
54 ++parts_index_;
55 reopen_(this);
56 header_written_ = false;
Austin Schuh5e14d842022-01-21 12:02:15 -080057 for (State &state : state_) {
58 state.boot_uuid = UUID::Zero();
59 state.oldest_remote_monotonic_timestamp = monotonic_clock::max_time;
60 state.oldest_local_monotonic_timestamp = monotonic_clock::max_time;
61 state.oldest_remote_unreliable_monotonic_timestamp =
62 monotonic_clock::max_time;
63 state.oldest_local_unreliable_monotonic_timestamp =
64 monotonic_clock::max_time;
Austin Schuhbfe6c572022-01-27 20:48:20 -080065 state.oldest_remote_reliable_monotonic_timestamp =
66 monotonic_clock::max_time;
Austin Schuhf5f99f32022-02-07 20:05:37 -080067 state.oldest_local_reliable_monotonic_timestamp = monotonic_clock::max_time;
68 state.oldest_logger_remote_unreliable_monotonic_timestamp =
69 monotonic_clock::max_time;
70 state.oldest_logger_local_unreliable_monotonic_timestamp =
Austin Schuhbfe6c572022-01-27 20:48:20 -080071 monotonic_clock::max_time;
Austin Schuh5e14d842022-01-21 12:02:15 -080072 }
73
74 state_[node_index_].boot_uuid = source_node_boot_uuid;
75
76 VLOG(1) << "Rebooted " << filename();
77}
78
79void NewDataWriter::UpdateBoot(const UUID &source_node_boot_uuid) {
80 if (state_[node_index_].boot_uuid != source_node_boot_uuid) {
81 state_[node_index_].boot_uuid = source_node_boot_uuid;
82 if (header_written_) {
83 Reboot(source_node_boot_uuid);
84 }
85 }
Austin Schuh572924a2021-07-30 22:32:12 -070086}
87
Austin Schuh72211ae2021-08-05 14:02:30 -070088void NewDataWriter::UpdateRemote(
89 const size_t remote_node_index, const UUID &remote_node_boot_uuid,
90 const monotonic_clock::time_point monotonic_remote_time,
Austin Schuhf5f99f32022-02-07 20:05:37 -080091 const monotonic_clock::time_point monotonic_event_time, const bool reliable,
92 monotonic_clock::time_point monotonic_timestamp_time) {
Austin Schuh58646e22021-08-23 23:51:46 -070093 // Trigger rotation if anything in the header changes.
Austin Schuh72211ae2021-08-05 14:02:30 -070094 bool rotate = false;
95 CHECK_LT(remote_node_index, state_.size());
96 State &state = state_[remote_node_index];
Austin Schuh58646e22021-08-23 23:51:46 -070097
98 // Did the remote boot UUID change?
Austin Schuh72211ae2021-08-05 14:02:30 -070099 if (state.boot_uuid != remote_node_boot_uuid) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700100 VLOG(1) << filename() << " Remote " << remote_node_index << " updated to "
Austin Schuh72211ae2021-08-05 14:02:30 -0700101 << remote_node_boot_uuid << " from " << state.boot_uuid;
102 state.boot_uuid = remote_node_boot_uuid;
103 state.oldest_remote_monotonic_timestamp = monotonic_clock::max_time;
104 state.oldest_local_monotonic_timestamp = monotonic_clock::max_time;
105 state.oldest_remote_unreliable_monotonic_timestamp =
106 monotonic_clock::max_time;
107 state.oldest_local_unreliable_monotonic_timestamp =
108 monotonic_clock::max_time;
Austin Schuhbfe6c572022-01-27 20:48:20 -0800109 state.oldest_remote_reliable_monotonic_timestamp =
110 monotonic_clock::max_time;
Austin Schuhf5f99f32022-02-07 20:05:37 -0800111 state.oldest_local_reliable_monotonic_timestamp = monotonic_clock::max_time;
112 state.oldest_logger_remote_unreliable_monotonic_timestamp =
113 monotonic_clock::max_time;
114 state.oldest_logger_local_unreliable_monotonic_timestamp =
Austin Schuhbfe6c572022-01-27 20:48:20 -0800115 monotonic_clock::max_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700116 rotate = true;
117 }
118
Austin Schuh58646e22021-08-23 23:51:46 -0700119 // Did the unreliable timestamps change?
Austin Schuh72211ae2021-08-05 14:02:30 -0700120 if (!reliable) {
121 if (state.oldest_remote_unreliable_monotonic_timestamp >
122 monotonic_remote_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700123 VLOG(1) << filename() << " Remote " << remote_node_index
124 << " oldest_remote_unreliable_monotonic_timestamp updated from "
125 << state.oldest_remote_unreliable_monotonic_timestamp << " to "
126 << monotonic_remote_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700127 state.oldest_remote_unreliable_monotonic_timestamp =
128 monotonic_remote_time;
129 state.oldest_local_unreliable_monotonic_timestamp = monotonic_event_time;
130 rotate = true;
131 }
Austin Schuhbfe6c572022-01-27 20:48:20 -0800132 } else {
133 if (state.oldest_remote_reliable_monotonic_timestamp >
134 monotonic_remote_time) {
135 VLOG(1) << filename() << " Remote " << remote_node_index
136 << " oldest_remote_reliable_monotonic_timestamp updated from "
137 << state.oldest_remote_reliable_monotonic_timestamp << " to "
138 << monotonic_remote_time;
139 state.oldest_remote_reliable_monotonic_timestamp = monotonic_remote_time;
140 state.oldest_local_reliable_monotonic_timestamp = monotonic_event_time;
141 rotate = true;
142 }
Austin Schuh72211ae2021-08-05 14:02:30 -0700143 }
144
Austin Schuhf5f99f32022-02-07 20:05:37 -0800145 // Track the logger timestamps too.
146 if (monotonic_timestamp_time != monotonic_clock::min_time) {
147 State &logger_state = state_[node_index_];
148 CHECK_EQ(remote_node_index, logger_node_index_);
149 if (monotonic_event_time <
150 logger_state.oldest_logger_remote_unreliable_monotonic_timestamp) {
151 VLOG(1)
152 << filename() << " Remote " << node_index_
153 << " oldest_logger_remote_unreliable_monotonic_timestamp updated "
154 "from "
155 << logger_state.oldest_logger_remote_unreliable_monotonic_timestamp
156 << " to " << monotonic_event_time;
157 logger_state.oldest_logger_remote_unreliable_monotonic_timestamp =
158 monotonic_event_time;
159 logger_state.oldest_logger_local_unreliable_monotonic_timestamp =
160 monotonic_timestamp_time;
161
162 rotate = true;
163 }
164 }
165
Austin Schuh58646e22021-08-23 23:51:46 -0700166 // Did any of the timestamps change?
Austin Schuh72211ae2021-08-05 14:02:30 -0700167 if (state.oldest_remote_monotonic_timestamp > monotonic_remote_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700168 VLOG(1) << filename() << " Remote " << remote_node_index
169 << " oldest_remote_monotonic_timestamp updated from "
170 << state.oldest_remote_monotonic_timestamp << " to "
171 << monotonic_remote_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700172 state.oldest_remote_monotonic_timestamp = monotonic_remote_time;
173 state.oldest_local_monotonic_timestamp = monotonic_event_time;
174 rotate = true;
175 }
176
177 if (rotate) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700178 Rotate();
179 }
180}
181
182void NewDataWriter::QueueMessage(flatbuffers::FlatBufferBuilder *fbb,
183 const UUID &source_node_boot_uuid,
184 aos::monotonic_clock::time_point now) {
Austin Schuh58646e22021-08-23 23:51:46 -0700185 // Trigger a reboot if we detect the boot UUID change.
Austin Schuh5e14d842022-01-21 12:02:15 -0800186 UpdateBoot(source_node_boot_uuid);
Austin Schuh572924a2021-07-30 22:32:12 -0700187
Austin Schuh5e14d842022-01-21 12:02:15 -0800188 if (!header_written_) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700189 QueueHeader(MakeHeader());
Austin Schuh572924a2021-07-30 22:32:12 -0700190 }
Austin Schuh58646e22021-08-23 23:51:46 -0700191
192 // If the start time has changed for this node, trigger a rotation.
193 if (log_namer_->monotonic_start_time(node_index_, source_node_boot_uuid) !=
Austin Schuh5e14d842022-01-21 12:02:15 -0800194 monotonic_start_time_) {
Austin Schuh58646e22021-08-23 23:51:46 -0700195 CHECK(header_written_);
196 Rotate();
197 }
198
199 CHECK_EQ(log_namer_->monotonic_start_time(node_index_, source_node_boot_uuid),
200 monotonic_start_time_);
Austin Schuh72211ae2021-08-05 14:02:30 -0700201 CHECK_EQ(state_[node_index_].boot_uuid, source_node_boot_uuid);
milind-ua50344f2021-08-25 18:22:20 -0700202 CHECK(writer);
Austin Schuh572924a2021-07-30 22:32:12 -0700203 CHECK(header_written_) << ": Attempting to write message before header to "
204 << writer->filename();
205 writer->QueueSizedFlatbuffer(fbb, now);
206}
207
Austin Schuhe46492f2021-07-31 19:49:41 -0700208aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader>
209NewDataWriter::MakeHeader() {
210 const size_t logger_node_index = log_namer_->logger_node_index();
211 const UUID &logger_node_boot_uuid = log_namer_->logger_node_boot_uuid();
Austin Schuh72211ae2021-08-05 14:02:30 -0700212 if (state_[logger_node_index].boot_uuid == UUID::Zero()) {
Austin Schuhe46492f2021-07-31 19:49:41 -0700213 VLOG(1) << filename() << " Logger node is " << logger_node_index
214 << " and uuid is " << logger_node_boot_uuid;
Austin Schuh72211ae2021-08-05 14:02:30 -0700215 state_[logger_node_index].boot_uuid = logger_node_boot_uuid;
Austin Schuhe46492f2021-07-31 19:49:41 -0700216 } else {
Austin Schuh72211ae2021-08-05 14:02:30 -0700217 CHECK_EQ(state_[logger_node_index].boot_uuid, logger_node_boot_uuid);
Austin Schuhe46492f2021-07-31 19:49:41 -0700218 }
Austin Schuh72211ae2021-08-05 14:02:30 -0700219 return log_namer_->MakeHeader(node_index_, state_, parts_uuid(),
Austin Schuhe46492f2021-07-31 19:49:41 -0700220 parts_index_);
221}
222
Austin Schuh572924a2021-07-30 22:32:12 -0700223void NewDataWriter::QueueHeader(
224 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> &&header) {
225 CHECK(!header_written_) << ": Attempting to write duplicate header to "
226 << writer->filename();
227 CHECK(header.message().has_source_node_boot_uuid());
Austin Schuh72211ae2021-08-05 14:02:30 -0700228 CHECK_EQ(state_[node_index_].boot_uuid,
Austin Schuhe46492f2021-07-31 19:49:41 -0700229 UUID::FromString(header.message().source_node_boot_uuid()));
Austin Schuh510dc622021-08-06 18:47:30 -0700230 if (!writer) {
231 reopen_(this);
232 }
233
Austin Schuh58646e22021-08-23 23:51:46 -0700234 VLOG(1) << "Writing to " << filename() << " "
235 << aos::FlatbufferToJson(
236 header, {.multi_line = false, .max_vector_size = 100});
237
Austin Schuh572924a2021-07-30 22:32:12 -0700238 // TODO(austin): This triggers a dummy allocation that we don't need as part
239 // of releasing. Can we skip it?
Austin Schuh510dc622021-08-06 18:47:30 -0700240 CHECK(writer);
Austin Schuh572924a2021-07-30 22:32:12 -0700241 writer->QueueSizedFlatbuffer(header.Release());
242 header_written_ = true;
Austin Schuh58646e22021-08-23 23:51:46 -0700243 monotonic_start_time_ = log_namer_->monotonic_start_time(
244 node_index_, state_[node_index_].boot_uuid);
Austin Schuh572924a2021-07-30 22:32:12 -0700245}
246
247void NewDataWriter::Close() {
248 CHECK(writer);
249 close_(this);
250 writer.reset();
251 header_written_ = false;
252}
253
Austin Schuh58646e22021-08-23 23:51:46 -0700254LogNamer::NodeState *LogNamer::GetNodeState(size_t node_index,
255 const UUID &boot_uuid) {
256 auto it = node_states_.find(std::make_pair(node_index, boot_uuid));
257 if (it == node_states_.end()) {
258 it =
259 node_states_.emplace(std::make_pair(node_index, boot_uuid), NodeState())
260 .first;
261 }
262 return &it->second;
263}
264
Austin Schuh73340842021-07-30 22:32:06 -0700265aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> LogNamer::MakeHeader(
Austin Schuh72211ae2021-08-05 14:02:30 -0700266 size_t node_index, const std::vector<NewDataWriter::State> &state,
Austin Schuh58646e22021-08-23 23:51:46 -0700267 const UUID &parts_uuid, int parts_index) {
Austin Schuh72211ae2021-08-05 14:02:30 -0700268 const UUID &source_node_boot_uuid = state[node_index].boot_uuid;
Austin Schuh73340842021-07-30 22:32:06 -0700269 const Node *const source_node =
270 configuration::GetNode(configuration_, node_index);
Austin Schuhfa712682022-05-11 16:43:42 -0700271 CHECK_EQ(LogFileHeader::MiniReflectTypeTable()->num_elems, 34u);
Austin Schuh73340842021-07-30 22:32:06 -0700272 flatbuffers::FlatBufferBuilder fbb;
273 fbb.ForceDefaults(true);
274
275 flatbuffers::Offset<flatbuffers::String> config_sha256_offset;
276 flatbuffers::Offset<aos::Configuration> configuration_offset;
277 if (header_.message().has_configuration()) {
278 CHECK(!header_.message().has_configuration_sha256());
279 configuration_offset =
280 CopyFlatBuffer(header_.message().configuration(), &fbb);
281 } else {
282 CHECK(!header_.message().has_configuration());
283 CHECK(header_.message().has_configuration_sha256());
284 config_sha256_offset = fbb.CreateString(
285 header_.message().configuration_sha256()->string_view());
286 }
287
288 CHECK(header_.message().has_name());
289 const flatbuffers::Offset<flatbuffers::String> name_offset =
290 fbb.CreateString(header_.message().name()->string_view());
Austin Schuhfa712682022-05-11 16:43:42 -0700291 const flatbuffers::Offset<flatbuffers::String> logger_sha1_offset =
292 header_.message().has_logger_sha1()
293 ? fbb.CreateString(header_.message().logger_sha1()->string_view())
294 : 0;
295 const flatbuffers::Offset<flatbuffers::String> logger_version_offset =
296 header_.message().has_logger_version()
297 ? fbb.CreateString(header_.message().logger_version()->string_view())
298 : 0;
Austin Schuh73340842021-07-30 22:32:06 -0700299
300 CHECK(header_.message().has_log_event_uuid());
301 const flatbuffers::Offset<flatbuffers::String> log_event_uuid_offset =
302 fbb.CreateString(header_.message().log_event_uuid()->string_view());
303
304 CHECK(header_.message().has_logger_instance_uuid());
305 const flatbuffers::Offset<flatbuffers::String> logger_instance_uuid_offset =
306 fbb.CreateString(header_.message().logger_instance_uuid()->string_view());
307
308 flatbuffers::Offset<flatbuffers::String> log_start_uuid_offset;
309 if (header_.message().has_log_start_uuid()) {
310 log_start_uuid_offset =
311 fbb.CreateString(header_.message().log_start_uuid()->string_view());
312 }
313
314 CHECK(header_.message().has_logger_node_boot_uuid());
315 const flatbuffers::Offset<flatbuffers::String> logger_node_boot_uuid_offset =
316 fbb.CreateString(
317 header_.message().logger_node_boot_uuid()->string_view());
318
319 CHECK_NE(source_node_boot_uuid, UUID::Zero());
320 const flatbuffers::Offset<flatbuffers::String> source_node_boot_uuid_offset =
321 source_node_boot_uuid.PackString(&fbb);
322
323 const flatbuffers::Offset<flatbuffers::String> parts_uuid_offset =
324 parts_uuid.PackString(&fbb);
325
326 flatbuffers::Offset<Node> node_offset;
327 flatbuffers::Offset<Node> logger_node_offset;
328
329 if (configuration::MultiNode(configuration_)) {
330 node_offset = RecursiveCopyFlatBuffer(source_node, &fbb);
331 logger_node_offset = RecursiveCopyFlatBuffer(node_, &fbb);
332 }
333
Austin Schuhe46492f2021-07-31 19:49:41 -0700334 std::vector<flatbuffers::Offset<flatbuffers::String>> boot_uuid_offsets;
Austin Schuh72211ae2021-08-05 14:02:30 -0700335 boot_uuid_offsets.reserve(state.size());
Austin Schuhe46492f2021-07-31 19:49:41 -0700336
Austin Schuh4db9ec92021-09-22 13:11:12 -0700337 int64_t *unused;
Austin Schuh72211ae2021-08-05 14:02:30 -0700338 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
Austin Schuhf5f99f32022-02-07 20:05:37 -0800339 oldest_remote_monotonic_timestamps_offset =
340 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700341
Austin Schuh72211ae2021-08-05 14:02:30 -0700342 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
Austin Schuhf5f99f32022-02-07 20:05:37 -0800343 oldest_local_monotonic_timestamps_offset =
344 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700345
Austin Schuh72211ae2021-08-05 14:02:30 -0700346 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
347 oldest_remote_unreliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800348 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700349
Austin Schuh72211ae2021-08-05 14:02:30 -0700350 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
351 oldest_local_unreliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800352 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuh72211ae2021-08-05 14:02:30 -0700353
Austin Schuhbfe6c572022-01-27 20:48:20 -0800354 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
355 oldest_remote_reliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800356 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800357
358 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
359 oldest_local_reliable_monotonic_timestamps_offset =
Austin Schuhf5f99f32022-02-07 20:05:37 -0800360 fbb.CreateUninitializedVector(state.size(), &unused);
361
362 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
363 oldest_logger_remote_unreliable_monotonic_timestamps_offset =
364 fbb.CreateUninitializedVector(state.size(), &unused);
365
366 flatbuffers::Offset<flatbuffers::Vector<int64_t>>
367 oldest_logger_local_unreliable_monotonic_timestamps_offset =
368 fbb.CreateUninitializedVector(state.size(), &unused);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800369
Austin Schuh72211ae2021-08-05 14:02:30 -0700370 for (size_t i = 0; i < state.size(); ++i) {
Austin Schuh4db9ec92021-09-22 13:11:12 -0700371 if (state[i].boot_uuid != UUID::Zero()) {
372 boot_uuid_offsets.emplace_back(state[i].boot_uuid.PackString(&fbb));
373 } else {
374 boot_uuid_offsets.emplace_back(fbb.CreateString(""));
375 }
Austin Schuh5ae8f4a2021-09-11 19:09:50 -0700376 if (state[i].boot_uuid == UUID::Zero()) {
377 CHECK_EQ(state[i].oldest_remote_monotonic_timestamp,
378 monotonic_clock::max_time);
379 CHECK_EQ(state[i].oldest_local_monotonic_timestamp,
380 monotonic_clock::max_time);
381 CHECK_EQ(state[i].oldest_remote_unreliable_monotonic_timestamp,
382 monotonic_clock::max_time);
383 CHECK_EQ(state[i].oldest_local_unreliable_monotonic_timestamp,
384 monotonic_clock::max_time);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800385 CHECK_EQ(state[i].oldest_remote_reliable_monotonic_timestamp,
386 monotonic_clock::max_time);
387 CHECK_EQ(state[i].oldest_local_reliable_monotonic_timestamp,
388 monotonic_clock::max_time);
Austin Schuhf5f99f32022-02-07 20:05:37 -0800389 CHECK_EQ(state[i].oldest_logger_remote_unreliable_monotonic_timestamp,
390 monotonic_clock::max_time);
391 CHECK_EQ(state[i].oldest_logger_local_unreliable_monotonic_timestamp,
392 monotonic_clock::max_time);
Austin Schuh5ae8f4a2021-09-11 19:09:50 -0700393 }
394
Austin Schuh4db9ec92021-09-22 13:11:12 -0700395 flatbuffers::GetMutableTemporaryPointer(
396 fbb, oldest_remote_monotonic_timestamps_offset)
397 ->Mutate(i, state[i]
398 .oldest_remote_monotonic_timestamp.time_since_epoch()
399 .count());
400 flatbuffers::GetMutableTemporaryPointer(
401 fbb, oldest_local_monotonic_timestamps_offset)
402 ->Mutate(i, state[i]
403 .oldest_local_monotonic_timestamp.time_since_epoch()
404 .count());
405 flatbuffers::GetMutableTemporaryPointer(
406 fbb, oldest_remote_unreliable_monotonic_timestamps_offset)
407 ->Mutate(i, state[i]
Austin Schuhbfe6c572022-01-27 20:48:20 -0800408 .oldest_remote_unreliable_monotonic_timestamp
409 .time_since_epoch()
Austin Schuh4db9ec92021-09-22 13:11:12 -0700410 .count());
411 flatbuffers::GetMutableTemporaryPointer(
412 fbb, oldest_local_unreliable_monotonic_timestamps_offset)
413 ->Mutate(i, state[i]
Austin Schuhbfe6c572022-01-27 20:48:20 -0800414 .oldest_local_unreliable_monotonic_timestamp
415 .time_since_epoch()
Austin Schuh4db9ec92021-09-22 13:11:12 -0700416 .count());
Austin Schuhbfe6c572022-01-27 20:48:20 -0800417
418 flatbuffers::GetMutableTemporaryPointer(
419 fbb, oldest_remote_reliable_monotonic_timestamps_offset)
420 ->Mutate(i, state[i]
421 .oldest_remote_reliable_monotonic_timestamp
422 .time_since_epoch()
423 .count());
424 flatbuffers::GetMutableTemporaryPointer(
425 fbb, oldest_local_reliable_monotonic_timestamps_offset)
426 ->Mutate(
427 i, state[i]
428 .oldest_local_reliable_monotonic_timestamp.time_since_epoch()
429 .count());
Austin Schuhf5f99f32022-02-07 20:05:37 -0800430
431 flatbuffers::GetMutableTemporaryPointer(
432 fbb, oldest_logger_remote_unreliable_monotonic_timestamps_offset)
433 ->Mutate(i, state[i]
434 .oldest_logger_remote_unreliable_monotonic_timestamp
435 .time_since_epoch()
436 .count());
437 flatbuffers::GetMutableTemporaryPointer(
438 fbb, oldest_logger_local_unreliable_monotonic_timestamps_offset)
439 ->Mutate(i, state[i]
440 .oldest_logger_local_unreliable_monotonic_timestamp
441 .time_since_epoch()
442 .count());
Austin Schuh72211ae2021-08-05 14:02:30 -0700443 }
444
Austin Schuh4db9ec92021-09-22 13:11:12 -0700445 flatbuffers::Offset<
446 flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
447 boot_uuids_offset = fbb.CreateVector(boot_uuid_offsets);
448
Austin Schuh73340842021-07-30 22:32:06 -0700449 aos::logger::LogFileHeader::Builder log_file_header_builder(fbb);
450
451 log_file_header_builder.add_name(name_offset);
Austin Schuhfa712682022-05-11 16:43:42 -0700452 if (!logger_sha1_offset.IsNull()) {
453 log_file_header_builder.add_logger_sha1(logger_sha1_offset);
454 }
455 if (!logger_version_offset.IsNull()) {
456 log_file_header_builder.add_logger_version(logger_version_offset);
457 }
Austin Schuh73340842021-07-30 22:32:06 -0700458
459 // Only add the node if we are running in a multinode configuration.
460 if (!logger_node_offset.IsNull()) {
461 log_file_header_builder.add_node(node_offset);
462 log_file_header_builder.add_logger_node(logger_node_offset);
463 }
464
465 if (!configuration_offset.IsNull()) {
466 log_file_header_builder.add_configuration(configuration_offset);
467 }
468 log_file_header_builder.add_max_out_of_order_duration(
469 header_.message().max_out_of_order_duration());
470
Austin Schuh58646e22021-08-23 23:51:46 -0700471 NodeState *node_state = GetNodeState(node_index, source_node_boot_uuid);
Austin Schuh73340842021-07-30 22:32:06 -0700472 log_file_header_builder.add_monotonic_start_time(
473 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700474 node_state->monotonic_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700475 .count());
476 if (source_node == node_) {
477 log_file_header_builder.add_realtime_start_time(
478 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700479 node_state->realtime_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700480 .count());
481 } else {
482 // Fill out the legacy start times. Since these were implemented to never
483 // change on reboot, they aren't very helpful in tracking what happened.
484 log_file_header_builder.add_logger_monotonic_start_time(
485 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700486 node_state->logger_monotonic_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700487 .count());
488 log_file_header_builder.add_logger_realtime_start_time(
489 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh58646e22021-08-23 23:51:46 -0700490 node_state->logger_realtime_start_time.time_since_epoch())
Austin Schuh73340842021-07-30 22:32:06 -0700491 .count());
492 }
493
494 // TODO(austin): Add more useful times. When was this part started? What do
495 // we know about both the logger and remote then?
496
497 log_file_header_builder.add_log_event_uuid(log_event_uuid_offset);
498 log_file_header_builder.add_logger_instance_uuid(logger_instance_uuid_offset);
499 if (!log_start_uuid_offset.IsNull()) {
500 log_file_header_builder.add_log_start_uuid(log_start_uuid_offset);
501 }
502 log_file_header_builder.add_logger_node_boot_uuid(
503 logger_node_boot_uuid_offset);
504 log_file_header_builder.add_source_node_boot_uuid(
505 source_node_boot_uuid_offset);
506
507 log_file_header_builder.add_parts_uuid(parts_uuid_offset);
508 log_file_header_builder.add_parts_index(parts_index);
509
510 if (!config_sha256_offset.IsNull()) {
511 log_file_header_builder.add_configuration_sha256(config_sha256_offset);
512 }
513
Austin Schuhe46492f2021-07-31 19:49:41 -0700514 log_file_header_builder.add_boot_uuids(boot_uuids_offset);
Austin Schuha499cea2021-07-31 19:49:53 -0700515 log_file_header_builder.add_logger_part_monotonic_start_time(
516 std::chrono::duration_cast<std::chrono::nanoseconds>(
517 event_loop_->monotonic_now().time_since_epoch())
518 .count());
519 log_file_header_builder.add_logger_part_realtime_start_time(
520 std::chrono::duration_cast<std::chrono::nanoseconds>(
521 event_loop_->realtime_now().time_since_epoch())
522 .count());
Austin Schuh72211ae2021-08-05 14:02:30 -0700523 log_file_header_builder.add_oldest_remote_monotonic_timestamps(
524 oldest_remote_monotonic_timestamps_offset);
525 log_file_header_builder.add_oldest_local_monotonic_timestamps(
526 oldest_local_monotonic_timestamps_offset);
527 log_file_header_builder.add_oldest_remote_unreliable_monotonic_timestamps(
528 oldest_remote_unreliable_monotonic_timestamps_offset);
529 log_file_header_builder.add_oldest_local_unreliable_monotonic_timestamps(
530 oldest_local_unreliable_monotonic_timestamps_offset);
Austin Schuhbfe6c572022-01-27 20:48:20 -0800531 log_file_header_builder.add_oldest_remote_reliable_monotonic_timestamps(
532 oldest_remote_reliable_monotonic_timestamps_offset);
533 log_file_header_builder.add_oldest_local_reliable_monotonic_timestamps(
534 oldest_local_reliable_monotonic_timestamps_offset);
Austin Schuhf5f99f32022-02-07 20:05:37 -0800535 log_file_header_builder
536 .add_oldest_logger_remote_unreliable_monotonic_timestamps(
537 oldest_logger_remote_unreliable_monotonic_timestamps_offset);
538 log_file_header_builder
539 .add_oldest_logger_local_unreliable_monotonic_timestamps(
540 oldest_logger_local_unreliable_monotonic_timestamps_offset);
Austin Schuh73340842021-07-30 22:32:06 -0700541 fbb.FinishSizePrefixed(log_file_header_builder.Finish());
542 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> result(
543 fbb.Release());
544
545 CHECK(result.Verify()) << ": Built a corrupted header.";
546
547 return result;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700548}
549
Austin Schuhb8bca732021-07-30 22:32:00 -0700550NewDataWriter *LocalLogNamer::MakeWriter(const Channel *channel) {
Austin Schuhdf576472020-10-19 09:39:37 -0700551 CHECK(configuration::ChannelIsSendableOnNode(channel, node()))
552 << ": " << configuration::CleanedChannelToString(channel);
Austin Schuhb8bca732021-07-30 22:32:00 -0700553 return &data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700554}
555
Austin Schuh73340842021-07-30 22:32:06 -0700556void LocalLogNamer::Rotate(const Node *node) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700557 CHECK(node == this->node());
Austin Schuhb8bca732021-07-30 22:32:00 -0700558 data_writer_.Rotate();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700559}
Austin Schuh8c399962020-12-25 21:51:45 -0800560
561void LocalLogNamer::WriteConfiguration(
562 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
563 std::string_view config_sha256) {
564 const std::string filename = absl::StrCat(base_name_, config_sha256, ".bfbs");
565
566 std::unique_ptr<DetachedBufferWriter> writer =
567 std::make_unique<DetachedBufferWriter>(
568 filename, std::make_unique<aos::logger::DummyEncoder>());
569 writer->QueueSizedFlatbuffer(header->Release());
570}
571
Austin Schuhb8bca732021-07-30 22:32:00 -0700572NewDataWriter *LocalLogNamer::MakeTimestampWriter(const Channel *channel) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700573 CHECK(configuration::ChannelIsReadableOnNode(channel, node_))
574 << ": Message is not delivered to this node.";
575 CHECK(node_ != nullptr) << ": Can't log timestamps in a single node world";
576 CHECK(configuration::ConnectionDeliveryTimeIsLoggedOnNode(channel, node_,
577 node_))
578 << ": Delivery times aren't logged for this channel on this node.";
Austin Schuhb8bca732021-07-30 22:32:00 -0700579 return &data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700580}
581
Austin Schuhb8bca732021-07-30 22:32:00 -0700582NewDataWriter *LocalLogNamer::MakeForwardedTimestampWriter(
Austin Schuhcb5601b2020-09-10 15:29:59 -0700583 const Channel * /*channel*/, const Node * /*node*/) {
584 LOG(FATAL) << "Can't log forwarded timestamps in a singe log file.";
585 return nullptr;
586}
Austin Schuhcb5601b2020-09-10 15:29:59 -0700587MultiNodeLogNamer::MultiNodeLogNamer(std::string_view base_name,
Austin Schuha499cea2021-07-31 19:49:53 -0700588 EventLoop *event_loop)
Austin Schuh5b728b72021-06-16 14:57:15 -0700589 : MultiNodeLogNamer(base_name, event_loop->configuration(), event_loop,
590 event_loop->node()) {}
591
592MultiNodeLogNamer::MultiNodeLogNamer(std::string_view base_name,
593 const Configuration *configuration,
594 EventLoop *event_loop, const Node *node)
595 : LogNamer(configuration, event_loop, node),
596 base_name_(base_name),
597 old_base_name_() {}
Austin Schuhcb5601b2020-09-10 15:29:59 -0700598
Brian Silverman48deab12020-09-30 18:39:28 -0700599MultiNodeLogNamer::~MultiNodeLogNamer() {
600 if (!ran_out_of_space_) {
601 // This handles renaming temporary files etc.
602 Close();
603 }
604}
605
Austin Schuh572924a2021-07-30 22:32:12 -0700606void MultiNodeLogNamer::Rotate(const Node *node) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700607 if (node == this->node()) {
Austin Schuhb8bca732021-07-30 22:32:00 -0700608 if (data_writer_) {
Austin Schuh572924a2021-07-30 22:32:12 -0700609 data_writer_->Rotate();
Brian Silvermancb805822020-10-06 17:43:35 -0700610 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700611 } else {
Austin Schuhb8bca732021-07-30 22:32:00 -0700612 for (std::pair<const Channel *const, NewDataWriter> &data_writer :
Austin Schuhcb5601b2020-09-10 15:29:59 -0700613 data_writers_) {
Austin Schuh572924a2021-07-30 22:32:12 -0700614 if (node == data_writer.second.node()) {
615 data_writer.second.Rotate();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700616 }
617 }
618 }
619}
620
Austin Schuh8c399962020-12-25 21:51:45 -0800621void MultiNodeLogNamer::WriteConfiguration(
622 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
623 std::string_view config_sha256) {
624 if (ran_out_of_space_) {
625 return;
626 }
627
628 const std::string_view separator = base_name_.back() == '/' ? "" : "_";
629 const std::string filename = absl::StrCat(
630 base_name_, separator, config_sha256, ".bfbs", extension_, temp_suffix_);
631
632 std::unique_ptr<DetachedBufferWriter> writer =
633 std::make_unique<DetachedBufferWriter>(filename, encoder_factory_());
634
635 writer->QueueSizedFlatbuffer(header->Release());
636
637 if (!writer->ran_out_of_space()) {
Austin Schuh5b728b72021-06-16 14:57:15 -0700638 all_filenames_.emplace_back(
639 absl::StrCat(config_sha256, ".bfbs", extension_));
Austin Schuh8c399962020-12-25 21:51:45 -0800640 }
641 CloseWriter(&writer);
642}
643
Austin Schuhb8bca732021-07-30 22:32:00 -0700644NewDataWriter *MultiNodeLogNamer::MakeWriter(const Channel *channel) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700645 // See if we can read the data on this node at all.
646 const bool is_readable =
647 configuration::ChannelIsReadableOnNode(channel, this->node());
648 if (!is_readable) {
649 return nullptr;
650 }
651
652 // Then, see if we are supposed to log the data here.
653 const bool log_message =
654 configuration::ChannelMessageIsLoggedOnNode(channel, this->node());
655
656 if (!log_message) {
657 return nullptr;
658 }
659
660 // Now, sort out if this is data generated on this node, or not. It is
661 // generated if it is sendable on this node.
662 if (configuration::ChannelIsSendableOnNode(channel, this->node())) {
Austin Schuhb8bca732021-07-30 22:32:00 -0700663 if (!data_writer_) {
Brian Silvermancb805822020-10-06 17:43:35 -0700664 OpenDataWriter();
665 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700666 return data_writer_.get();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700667 }
668
669 // Ok, we have data that is being forwarded to us that we are supposed to
670 // log. It needs to be logged with send timestamps, but be sorted enough
671 // to be able to be processed.
672 CHECK(data_writers_.find(channel) == data_writers_.end());
673
674 // Track that this node is being logged.
675 const Node *source_node = configuration::GetNode(
676 configuration_, channel->source_node()->string_view());
677
678 if (std::find(nodes_.begin(), nodes_.end(), source_node) == nodes_.end()) {
679 nodes_.emplace_back(source_node);
680 }
681
Austin Schuhf5f99f32022-02-07 20:05:37 -0800682 NewDataWriter data_writer(
683 this, source_node, node_,
684 [this, channel](NewDataWriter *data_writer) {
685 OpenWriter(channel, data_writer);
686 },
687 [this](NewDataWriter *data_writer) {
688 CloseWriter(&data_writer->writer);
689 });
Austin Schuhb8bca732021-07-30 22:32:00 -0700690 return &(
691 data_writers_.emplace(channel, std::move(data_writer)).first->second);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700692}
693
Austin Schuhb8bca732021-07-30 22:32:00 -0700694NewDataWriter *MultiNodeLogNamer::MakeForwardedTimestampWriter(
Austin Schuhcb5601b2020-09-10 15:29:59 -0700695 const Channel *channel, const Node *node) {
696 // See if we can read the data on this node at all.
697 const bool is_readable =
698 configuration::ChannelIsReadableOnNode(channel, this->node());
699 CHECK(is_readable) << ": " << configuration::CleanedChannelToString(channel);
700
701 CHECK(data_writers_.find(channel) == data_writers_.end());
702
703 if (std::find(nodes_.begin(), nodes_.end(), node) == nodes_.end()) {
704 nodes_.emplace_back(node);
705 }
706
Austin Schuhf5f99f32022-02-07 20:05:37 -0800707 NewDataWriter data_writer(
708 this, configuration::GetNode(configuration_, node), node_,
709 [this, channel](NewDataWriter *data_writer) {
710 OpenForwardedTimestampWriter(channel, data_writer);
711 },
712 [this](NewDataWriter *data_writer) {
713 CloseWriter(&data_writer->writer);
714 });
Austin Schuhb8bca732021-07-30 22:32:00 -0700715 return &(
716 data_writers_.emplace(channel, std::move(data_writer)).first->second);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700717}
718
Austin Schuhb8bca732021-07-30 22:32:00 -0700719NewDataWriter *MultiNodeLogNamer::MakeTimestampWriter(const Channel *channel) {
Brian Silverman0465fcf2020-09-24 00:29:18 -0700720 bool log_delivery_times = false;
721 if (this->node() != nullptr) {
722 log_delivery_times = configuration::ConnectionDeliveryTimeIsLoggedOnNode(
723 channel, this->node(), this->node());
724 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700725 if (!log_delivery_times) {
726 return nullptr;
727 }
728
Austin Schuhb8bca732021-07-30 22:32:00 -0700729 if (!data_writer_) {
Brian Silvermancb805822020-10-06 17:43:35 -0700730 OpenDataWriter();
731 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700732 return data_writer_.get();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700733}
734
Brian Silverman0465fcf2020-09-24 00:29:18 -0700735void MultiNodeLogNamer::Close() {
Austin Schuhb8bca732021-07-30 22:32:00 -0700736 data_writers_.clear();
737 data_writer_.reset();
Brian Silvermancb805822020-10-06 17:43:35 -0700738}
739
740void MultiNodeLogNamer::ResetStatistics() {
Austin Schuhb8bca732021-07-30 22:32:00 -0700741 for (std::pair<const Channel *const, NewDataWriter> &data_writer :
Brian Silvermancb805822020-10-06 17:43:35 -0700742 data_writers_) {
Austin Schuhad0cfc32020-12-21 12:34:26 -0800743 if (!data_writer.second.writer) continue;
Brian Silvermancb805822020-10-06 17:43:35 -0700744 data_writer.second.writer->ResetStatistics();
Brian Silverman0465fcf2020-09-24 00:29:18 -0700745 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700746 if (data_writer_) {
747 data_writer_->writer->ResetStatistics();
Brian Silvermancb805822020-10-06 17:43:35 -0700748 }
749 max_write_time_ = std::chrono::nanoseconds::zero();
750 max_write_time_bytes_ = -1;
751 max_write_time_messages_ = -1;
752 total_write_time_ = std::chrono::nanoseconds::zero();
753 total_write_count_ = 0;
754 total_write_messages_ = 0;
755 total_write_bytes_ = 0;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700756}
757
Austin Schuhb8bca732021-07-30 22:32:00 -0700758void MultiNodeLogNamer::OpenForwardedTimestampWriter(
759 const Channel *channel, NewDataWriter *data_writer) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700760 std::string filename =
Austin Schuhe715eae2020-10-10 15:39:30 -0700761 absl::StrCat("timestamps", channel->name()->string_view(), "/",
Brian Silvermana621f522020-09-30 16:52:43 -0700762 channel->type()->string_view(), ".part",
Austin Schuh572924a2021-07-30 22:32:12 -0700763 data_writer->parts_index(), ".bfbs", extension_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700764 CreateBufferWriter(filename, &data_writer->writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700765}
766
767void MultiNodeLogNamer::OpenWriter(const Channel *channel,
Austin Schuhb8bca732021-07-30 22:32:00 -0700768 NewDataWriter *data_writer) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700769 const std::string filename = absl::StrCat(
Austin Schuhe715eae2020-10-10 15:39:30 -0700770 CHECK_NOTNULL(channel->source_node())->string_view(), "_data",
Brian Silvermana621f522020-09-30 16:52:43 -0700771 channel->name()->string_view(), "/", channel->type()->string_view(),
Austin Schuh572924a2021-07-30 22:32:12 -0700772 ".part", data_writer->parts_index(), ".bfbs", extension_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700773 CreateBufferWriter(filename, &data_writer->writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700774}
775
Brian Silvermana621f522020-09-30 16:52:43 -0700776void MultiNodeLogNamer::OpenDataWriter() {
Austin Schuhb8bca732021-07-30 22:32:00 -0700777 if (!data_writer_) {
778 data_writer_ = std::make_unique<NewDataWriter>(
Austin Schuhf5f99f32022-02-07 20:05:37 -0800779 this, node_, node_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700780 [this](NewDataWriter *writer) {
781 std::string name;
782 if (node() != nullptr) {
783 name = absl::StrCat(name, node()->name()->string_view(), "_");
784 }
Austin Schuh572924a2021-07-30 22:32:12 -0700785 absl::StrAppend(&name, "data.part", writer->parts_index(), ".bfbs",
Austin Schuhb8bca732021-07-30 22:32:00 -0700786 extension_);
787 CreateBufferWriter(name, &writer->writer);
788 },
789 [this](NewDataWriter *data_writer) {
790 CloseWriter(&data_writer->writer);
791 });
Brian Silverman7af8c902020-09-29 16:14:04 -0700792 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700793}
794
Brian Silverman0465fcf2020-09-24 00:29:18 -0700795void MultiNodeLogNamer::CreateBufferWriter(
Brian Silvermana621f522020-09-30 16:52:43 -0700796 std::string_view path, std::unique_ptr<DetachedBufferWriter> *destination) {
Brian Silverman0465fcf2020-09-24 00:29:18 -0700797 if (ran_out_of_space_) {
798 // Refuse to open any new files, which might skip data. Any existing files
799 // are in the same folder, which means they're on the same filesystem, which
800 // means they're probably going to run out of space and get stuck too.
Austin Schuha426f1f2021-03-31 22:27:41 -0700801 if (!destination->get()) {
802 // But avoid leaving a nullptr writer if we're out of space when
803 // attempting to open the first file.
804 *destination = std::make_unique<DetachedBufferWriter>(
805 DetachedBufferWriter::already_out_of_space_t());
806 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700807 return;
808 }
Austin Schuhe715eae2020-10-10 15:39:30 -0700809 const std::string_view separator = base_name_.back() == '/' ? "" : "_";
810 const std::string filename =
811 absl::StrCat(base_name_, separator, path, temp_suffix_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700812 if (!destination->get()) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700813 if (ran_out_of_space_) {
814 *destination = std::make_unique<DetachedBufferWriter>(
815 DetachedBufferWriter::already_out_of_space_t());
816 return;
817 }
Brian Silvermancb805822020-10-06 17:43:35 -0700818 *destination =
819 std::make_unique<DetachedBufferWriter>(filename, encoder_factory_());
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700820 if (!destination->get()->ran_out_of_space()) {
821 all_filenames_.emplace_back(path);
822 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700823 return;
824 }
Brian Silvermancb805822020-10-06 17:43:35 -0700825
826 CloseWriter(destination);
827 if (ran_out_of_space_) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700828 *destination->get() =
829 DetachedBufferWriter(DetachedBufferWriter::already_out_of_space_t());
Brian Silverman0465fcf2020-09-24 00:29:18 -0700830 return;
831 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700832
Brian Silvermancb805822020-10-06 17:43:35 -0700833 *destination->get() = DetachedBufferWriter(filename, encoder_factory_());
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700834 if (!destination->get()->ran_out_of_space()) {
835 all_filenames_.emplace_back(path);
836 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700837}
838
Brian Silverman48deab12020-09-30 18:39:28 -0700839void MultiNodeLogNamer::RenameTempFile(DetachedBufferWriter *destination) {
840 if (temp_suffix_.empty()) {
841 return;
842 }
Austin Schuh6bb8a822021-03-31 23:04:39 -0700843 std::string current_filename = std::string(destination->filename());
Brian Silverman48deab12020-09-30 18:39:28 -0700844 CHECK(current_filename.size() > temp_suffix_.size());
Austin Schuh6bb8a822021-03-31 23:04:39 -0700845 std::string final_filename =
Brian Silverman48deab12020-09-30 18:39:28 -0700846 current_filename.substr(0, current_filename.size() - temp_suffix_.size());
Austin Schuh6bb8a822021-03-31 23:04:39 -0700847 int result = rename(current_filename.c_str(), final_filename.c_str());
848
849 // When changing the base name, we rename the log folder while there active
850 // buffer writers. Therefore, the name of that active buffer may still refer
851 // to the old file location rather than the new one. This minimized changes to
852 // existing code.
853 if (result != 0 && errno != ENOSPC && !old_base_name_.empty()) {
854 auto offset = current_filename.find(old_base_name_);
855 if (offset != std::string::npos) {
856 current_filename.replace(offset, old_base_name_.length(), base_name_);
857 }
858 offset = final_filename.find(old_base_name_);
859 if (offset != std::string::npos) {
860 final_filename.replace(offset, old_base_name_.length(), base_name_);
861 }
862 result = rename(current_filename.c_str(), final_filename.c_str());
863 }
864
Brian Silverman48deab12020-09-30 18:39:28 -0700865 if (result != 0) {
866 if (errno == ENOSPC) {
867 ran_out_of_space_ = true;
868 return;
869 } else {
870 PLOG(FATAL) << "Renaming " << current_filename << " to " << final_filename
871 << " failed";
872 }
Austin Schuh6bb8a822021-03-31 23:04:39 -0700873 } else {
874 VLOG(1) << "Renamed " << current_filename << " -> " << final_filename;
Brian Silverman48deab12020-09-30 18:39:28 -0700875 }
876}
877
Brian Silvermancb805822020-10-06 17:43:35 -0700878void MultiNodeLogNamer::CloseWriter(
879 std::unique_ptr<DetachedBufferWriter> *writer_pointer) {
880 DetachedBufferWriter *const writer = writer_pointer->get();
881 if (!writer) {
882 return;
883 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700884 const bool was_open = writer->is_open();
Brian Silvermancb805822020-10-06 17:43:35 -0700885 writer->Close();
886
887 if (writer->max_write_time() > max_write_time_) {
888 max_write_time_ = writer->max_write_time();
889 max_write_time_bytes_ = writer->max_write_time_bytes();
890 max_write_time_messages_ = writer->max_write_time_messages();
891 }
892 total_write_time_ += writer->total_write_time();
893 total_write_count_ += writer->total_write_count();
894 total_write_messages_ += writer->total_write_messages();
895 total_write_bytes_ += writer->total_write_bytes();
896
897 if (writer->ran_out_of_space()) {
898 ran_out_of_space_ = true;
899 writer->acknowledge_out_of_space();
900 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700901 if (was_open) {
902 RenameTempFile(writer);
903 } else {
904 CHECK(access(std::string(writer->filename()).c_str(), F_OK) == -1)
905 << ": File should not exist: " << writer->filename();
906 }
Brian Silvermancb805822020-10-06 17:43:35 -0700907}
908
Austin Schuhcb5601b2020-09-10 15:29:59 -0700909} // namespace logger
910} // namespace aos