Austin Schuh | cb5601b | 2020-09-10 15:29:59 -0700 | [diff] [blame] | 1 | #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 | |
| 15 | namespace aos { |
| 16 | namespace logger { |
| 17 | |
| 18 | // Interface describing how to name, track, and add headers to log file parts. |
| 19 | class 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 | |
Brian Silverman | 87ac040 | 2020-09-17 14:47:01 -0700 | [diff] [blame] | 36 | // Returns a writer for writing data from messages on this channel (on the |
| 37 | // primary node). |
| 38 | // |
| 39 | // The returned pointer will stay valid across rotations, but the object it |
| 40 | // points to will be assigned to. |
Austin Schuh | cb5601b | 2020-09-10 15:29:59 -0700 | [diff] [blame] | 41 | virtual DetachedBufferWriter *MakeWriter(const Channel *channel) = 0; |
| 42 | |
Brian Silverman | 87ac040 | 2020-09-17 14:47:01 -0700 | [diff] [blame] | 43 | // Returns a writer for writing timestamps from messages on this channel (on |
| 44 | // the primary node). |
| 45 | // |
| 46 | // The returned pointer will stay valid across rotations, but the object it |
| 47 | // points to will be assigned to. |
Austin Schuh | cb5601b | 2020-09-10 15:29:59 -0700 | [diff] [blame] | 48 | virtual DetachedBufferWriter *MakeTimestampWriter(const Channel *channel) = 0; |
| 49 | |
| 50 | // Returns a writer for writing timestamps delivered over the special |
| 51 | // /aos/remote_timestamps/* channels. node is the node that the timestamps |
Brian Silverman | 87ac040 | 2020-09-17 14:47:01 -0700 | [diff] [blame] | 52 | // are forwarded back from (to the primary node). |
| 53 | // |
| 54 | // The returned pointer will stay valid across rotations, but the object it |
| 55 | // points to will be assigned to. |
Austin Schuh | cb5601b | 2020-09-10 15:29:59 -0700 | [diff] [blame] | 56 | virtual DetachedBufferWriter *MakeForwardedTimestampWriter( |
| 57 | const Channel *channel, const Node *node) = 0; |
| 58 | |
| 59 | // Rotates all log files for the provided node. The provided header will be |
| 60 | // modified and written per WriteHeader above. |
| 61 | virtual void Rotate( |
| 62 | const Node *node, |
| 63 | aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) = 0; |
| 64 | |
| 65 | // Returns all the nodes that data is being written for. |
| 66 | const std::vector<const Node *> &nodes() const { return nodes_; } |
| 67 | |
| 68 | // Returns the node the logger is running on. |
| 69 | const Node *node() const { return node_; } |
| 70 | |
| 71 | protected: |
| 72 | // Modifies the header to have the provided UUID and part id. |
| 73 | void UpdateHeader( |
| 74 | aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header, |
| 75 | const UUID &uuid, int part_id) const; |
| 76 | |
| 77 | const Node *const node_; |
| 78 | std::vector<const Node *> nodes_; |
| 79 | }; |
| 80 | |
| 81 | // Local log namer is a simple version which only names things |
| 82 | // "base_name.part#.bfbs" and increments the part number. It doesn't support |
| 83 | // any other log type. |
| 84 | class LocalLogNamer : public LogNamer { |
| 85 | public: |
| 86 | LocalLogNamer(std::string_view base_name, const Node *node) |
| 87 | : LogNamer(node), |
| 88 | base_name_(base_name), |
| 89 | uuid_(UUID::Random()), |
| 90 | data_writer_(OpenDataWriter()) {} |
| 91 | |
| 92 | void WriteHeader( |
| 93 | aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header, |
| 94 | const Node *node) override; |
| 95 | |
| 96 | DetachedBufferWriter *MakeWriter(const Channel *channel) override; |
| 97 | |
| 98 | void Rotate(const Node *node, |
| 99 | aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) |
| 100 | override; |
| 101 | |
| 102 | DetachedBufferWriter *MakeTimestampWriter(const Channel *channel) override; |
| 103 | |
| 104 | DetachedBufferWriter *MakeForwardedTimestampWriter( |
| 105 | const Channel * /*channel*/, const Node * /*node*/) override; |
| 106 | |
| 107 | private: |
| 108 | // Creates a new data writer with the new part number. |
| 109 | std::unique_ptr<DetachedBufferWriter> OpenDataWriter() { |
| 110 | return std::make_unique<DetachedBufferWriter>( |
| 111 | absl::StrCat(base_name_, ".part", part_number_, ".bfbs")); |
| 112 | } |
| 113 | |
| 114 | const std::string base_name_; |
| 115 | const UUID uuid_; |
| 116 | size_t part_number_ = 0; |
| 117 | std::unique_ptr<DetachedBufferWriter> data_writer_; |
| 118 | }; |
| 119 | |
| 120 | // Log namer which uses a config and a base name to name a bunch of files. |
| 121 | class MultiNodeLogNamer : public LogNamer { |
| 122 | public: |
| 123 | MultiNodeLogNamer(std::string_view base_name, |
| 124 | const Configuration *configuration, const Node *node); |
| 125 | |
| 126 | void WriteHeader( |
| 127 | aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header, |
| 128 | const Node *node) override; |
| 129 | |
| 130 | void Rotate(const Node *node, |
| 131 | aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) |
| 132 | override; |
| 133 | |
| 134 | DetachedBufferWriter *MakeWriter(const Channel *channel) override; |
| 135 | |
Brian Silverman | d90905f | 2020-09-23 14:42:56 -0700 | [diff] [blame^] | 136 | DetachedBufferWriter *MakeForwardedTimestampWriter(const Channel *channel, |
| 137 | const Node *node) override; |
Austin Schuh | cb5601b | 2020-09-10 15:29:59 -0700 | [diff] [blame] | 138 | |
| 139 | DetachedBufferWriter *MakeTimestampWriter(const Channel *channel) override; |
| 140 | |
| 141 | private: |
| 142 | // Files to write remote data to. We want one per channel. Maps the channel |
| 143 | // to the writer, Node, and part number. |
| 144 | struct DataWriter { |
| 145 | std::unique_ptr<DetachedBufferWriter> writer = nullptr; |
| 146 | const Node *node; |
| 147 | size_t part_number = 0; |
| 148 | UUID uuid = UUID::Random(); |
| 149 | std::function<void(const Channel *, DataWriter *)> rotate; |
| 150 | }; |
| 151 | |
| 152 | // Opens up a writer for timestamps forwarded back. |
| 153 | void OpenForwardedTimestampWriter(const Channel *channel, |
| 154 | DataWriter *data_writer); |
| 155 | |
| 156 | // Opens up a writer for remote data. |
| 157 | void OpenWriter(const Channel *channel, DataWriter *data_writer); |
| 158 | |
| 159 | // Opens the main data writer file for this node responsible for data_writer_. |
| 160 | std::unique_ptr<DetachedBufferWriter> OpenDataWriter(); |
| 161 | |
| 162 | const std::string base_name_; |
| 163 | const Configuration *const configuration_; |
| 164 | const UUID uuid_; |
| 165 | |
| 166 | size_t part_number_ = 0; |
| 167 | |
| 168 | // File to write both delivery timestamps and local data to. |
| 169 | std::unique_ptr<DetachedBufferWriter> data_writer_; |
| 170 | |
| 171 | std::map<const Channel *, DataWriter> data_writers_; |
| 172 | }; |
| 173 | |
| 174 | } // namespace logger |
| 175 | } // namespace aos |
| 176 | |
| 177 | #endif // AOS_EVENTS_LOGGING_LOG_NAMER_H_ |