blob: 631016bc3c0f1c7b1119d472accf93b763406dac [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
10#include "aos/events/logging/logfile_utils.h"
11#include "aos/events/logging/logger_generated.h"
12#include "aos/events/logging/uuid.h"
13#include "flatbuffers/flatbuffers.h"
14
15namespace aos {
16namespace logger {
17
18// Interface describing how to name, track, and add headers to log file parts.
19class LogNamer {
20 public:
21 // Constructs a LogNamer with the primary node (ie the one the logger runs on)
22 // being node.
23 LogNamer(const Node *node) : node_(node) { nodes_.emplace_back(node_); }
24 virtual ~LogNamer() {}
25
26 // Writes the header to all log files for a specific node. This function
27 // needs to be called after all the writers are created.
28 //
29 // Modifies header to contain the uuid and part number for each writer as it
30 // writes it. Since this is done unconditionally, it does not restore the
31 // previous value at the end.
32 virtual void WriteHeader(
33 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
34 const Node *node) = 0;
35
36 // Returns a writer for writing data logged on this channel (on the node
37 // provided in the constructor).
38 virtual DetachedBufferWriter *MakeWriter(const Channel *channel) = 0;
39
40 // Returns a writer for writing timestamps logged on this channel (on the node
41 // provided in the constructor).
42 virtual DetachedBufferWriter *MakeTimestampWriter(const Channel *channel) = 0;
43
44 // Returns a writer for writing timestamps delivered over the special
45 // /aos/remote_timestamps/* channels. node is the node that the timestamps
46 // are forwarded back from.
47 virtual DetachedBufferWriter *MakeForwardedTimestampWriter(
48 const Channel *channel, const Node *node) = 0;
49
50 // Rotates all log files for the provided node. The provided header will be
51 // modified and written per WriteHeader above.
52 virtual void Rotate(
53 const Node *node,
54 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) = 0;
55
56 // Returns all the nodes that data is being written for.
57 const std::vector<const Node *> &nodes() const { return nodes_; }
58
59 // Returns the node the logger is running on.
60 const Node *node() const { return node_; }
61
62 protected:
63 // Modifies the header to have the provided UUID and part id.
64 void UpdateHeader(
65 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
66 const UUID &uuid, int part_id) const;
67
68 const Node *const node_;
69 std::vector<const Node *> nodes_;
70};
71
72// Local log namer is a simple version which only names things
73// "base_name.part#.bfbs" and increments the part number. It doesn't support
74// any other log type.
75class LocalLogNamer : public LogNamer {
76 public:
77 LocalLogNamer(std::string_view base_name, const Node *node)
78 : LogNamer(node),
79 base_name_(base_name),
80 uuid_(UUID::Random()),
81 data_writer_(OpenDataWriter()) {}
82
83 void WriteHeader(
84 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
85 const Node *node) override;
86
87 DetachedBufferWriter *MakeWriter(const Channel *channel) override;
88
89 void Rotate(const Node *node,
90 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header)
91 override;
92
93 DetachedBufferWriter *MakeTimestampWriter(const Channel *channel) override;
94
95 DetachedBufferWriter *MakeForwardedTimestampWriter(
96 const Channel * /*channel*/, const Node * /*node*/) override;
97
98 private:
99 // Creates a new data writer with the new part number.
100 std::unique_ptr<DetachedBufferWriter> OpenDataWriter() {
101 return std::make_unique<DetachedBufferWriter>(
102 absl::StrCat(base_name_, ".part", part_number_, ".bfbs"));
103 }
104
105 const std::string base_name_;
106 const UUID uuid_;
107 size_t part_number_ = 0;
108 std::unique_ptr<DetachedBufferWriter> data_writer_;
109};
110
111// Log namer which uses a config and a base name to name a bunch of files.
112class MultiNodeLogNamer : public LogNamer {
113 public:
114 MultiNodeLogNamer(std::string_view base_name,
115 const Configuration *configuration, const Node *node);
116
117 void WriteHeader(
118 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
119 const Node *node) override;
120
121 void Rotate(const Node *node,
122 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header)
123 override;
124
125 DetachedBufferWriter *MakeWriter(const Channel *channel) override;
126
127 DetachedBufferWriter *MakeForwardedTimestampWriter(
128 const Channel *channel, const Node *node) override;
129
130 DetachedBufferWriter *MakeTimestampWriter(const Channel *channel) override;
131
132 private:
133 // Files to write remote data to. We want one per channel. Maps the channel
134 // to the writer, Node, and part number.
135 struct DataWriter {
136 std::unique_ptr<DetachedBufferWriter> writer = nullptr;
137 const Node *node;
138 size_t part_number = 0;
139 UUID uuid = UUID::Random();
140 std::function<void(const Channel *, DataWriter *)> rotate;
141 };
142
143 // Opens up a writer for timestamps forwarded back.
144 void OpenForwardedTimestampWriter(const Channel *channel,
145 DataWriter *data_writer);
146
147 // Opens up a writer for remote data.
148 void OpenWriter(const Channel *channel, DataWriter *data_writer);
149
150 // Opens the main data writer file for this node responsible for data_writer_.
151 std::unique_ptr<DetachedBufferWriter> OpenDataWriter();
152
153 const std::string base_name_;
154 const Configuration *const configuration_;
155 const UUID uuid_;
156
157 size_t part_number_ = 0;
158
159 // File to write both delivery timestamps and local data to.
160 std::unique_ptr<DetachedBufferWriter> data_writer_;
161
162 std::map<const Channel *, DataWriter> data_writers_;
163};
164
165} // namespace logger
166} // namespace aos
167
168#endif // AOS_EVENTS_LOGGING_LOG_NAMER_H_