VLink  2.1.0
A high-performance communication middleware
vcap_writer.h
浏览该文件的文档.
1 /*
2  * Copyright (C) 2026 by Thun Lu. All rights reserved.
3  * Author: Thun Lu <thun.lu@zohomail.cn>
4  * Repo: https://github.com/thun-res/vlink
5  * _ __ __ _ __
6  * | | / / / / (_) ____ / /__
7  * | | / / / / / / / __ \ / //_/
8  * | |/ / / /___ / / / / / / / ,<
9  * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 
24 /**
25  * @file vcap_writer.h
26  * @brief Recorder that serialises VLink traffic into the MCAP container (@c .vcap / @c .vcapx).
27  *
28  * @details
29  * @c VCAPWriter materialises a @c BagWriter that emits Foxglove-compatible MCAP files. It
30  * inherits the cross-format split-recording machinery from @c BagWriter and produces files
31  * that any MCAP-aware tool can replay. Compression flips between no-compression and Zstd
32  * when the build links @c libzstd; other selectors degrade to plain chunks.
33  *
34  * @par File-format diagram
35  * @code
36  * push_schema() --> schema record
37  * push(frame) --> channel record (once per URL)
38  * --> message chunk (Zstd optional)
39  * close() --> attachments + summary section + footer (index of summary)
40  * @endcode
41  *
42  * @par Writer states
43  * @code
44  * +----------+ on_begin() +---------+ push()/push_schema() +-----------+
45  * | closed | ------------> | opening | -----------------------> | recording |
46  * +----------+ +---------+ +-----------+
47  * ^ |
48  * | v split triggered
49  * | +-------------+
50  * | | rotating |
51  * | | (new .vcap) |
52  * | +-------------+
53  * | |
54  * +-------------------- close() / dtor ---------------------- finalising
55  * |
56  * v
57  * sealed
58  * @endcode
59  *
60  * @par Example
61  * @code
62  * auto writer = vlink::BagWriter::create("/data/recording.vcap");
63  *
64  * writer->async_run();
65  * writer->push_schema(my_schema);
66  *
67  * vlink::Frame frame;
68  * frame.timestamp = -1; // < 0 => writer auto-assigns from its clock (0 is recorded verbatim)
69  * frame.url = "dds://lidar/front";
70  * frame.ser_type = "demo.proto.PointCloud";
71  * frame.schema_type = vlink::SchemaType::kProtobuf;
72  * frame.action_type = vlink::ActionType::kPublish;
73  * frame.data = serialized_bytes;
74  * writer->push(frame);
75  *
76  * writer->wait_for_idle();
77  * writer->quit();
78  * writer->wait_for_quit();
79  * writer->close();
80  * @endcode
81  *
82  * @see BagWriter, VDBWriter
83  */
84 
85 #pragma once
86 
87 #include <memory>
88 #include <string>
89 
90 #include "./bag_writer.h"
91 
92 namespace vlink {
93 
94 /**
95  * @class VCAPWriter
96  * @brief Concrete MCAP-format @c BagWriter implementation with optional Zstd compression.
97  *
98  * @details
99  * Prefer @c BagWriter::create() for format-agnostic instantiation; instantiate this class
100  * directly when an MCAP-specific feature is required.
101  */
102 class VLINK_EXPORT VCAPWriter final : public BagWriter {
103  public:
104  /**
105  * @brief Opens or creates an MCAP file for recording.
106  *
107  * @param path Filesystem path of the @c .vcap or @c .vcapx target.
108  * @param config Recording configuration (split policy, compression, etc.).
109  */
110  explicit VCAPWriter(const std::string& path, const Config& config = {});
111 
112  /**
113  * @brief Finalises the MCAP footer and flushes outstanding writes.
114  */
115  ~VCAPWriter() override;
116 
117  /**
118  * @brief Writes the channel metadata and MCAP footer, then closes the file; idempotent.
119  */
120  void close() override;
121 
122  /**
123  * @brief Registers a callback invoked at each file-split boundary.
124  *
125  * @param callback Receives (split_index, filename) before or after the split.
126  * @param before @c true fires before the new file is opened; @c false fires after.
127  */
128  void register_split_callback(SplitCallback&& callback, bool before) override;
129 
130  /**
131  * @brief Registers a resolver that maps a serialisation-type string to @c SchemaData.
132  *
133  * @param callback Function consulted before writing a channel record.
134  */
135  void register_schema_callback(SchemaCallback&& callback) override;
136 
137  /**
138  * @brief Embeds @p schema_data in the MCAP file for offline introspection.
139  *
140  * @param schema_data Schema descriptor to embed.
141  * @return @c false when a synchronous merge fails or an asynchronous merge cannot be queued.
142  */
143  bool push_schema(const SchemaData& schema_data) override;
144 
145  /**
146  * @brief Returns the current value of the internal dumping flag.
147  *
148  * @return @c true while messages are actively being persisted.
149  */
150  [[nodiscard]] bool is_dumping() const override;
151 
152  /**
153  * @brief Reports whether split-file recording is active.
154  *
155  * @return @c true when emitting a @c .vcapx manifest with multiple parts.
156  */
157  [[nodiscard]] bool is_split_mode() const override;
158 
159  /**
160  * @brief Returns the index of the split part currently being written.
161  *
162  * @return Zero-based split index.
163  */
164  [[nodiscard]] int get_split_index() const override;
165 
166  protected:
167  int64_t record(const Frame& frame, int64_t timestamp) override;
168 
169  int64_t get_record_timestamp() const override;
170 
171  size_t get_max_task_count() const override;
172 
173  void on_begin() override;
174 
175  void on_end() override;
176 
177  private:
178  void open(const std::string& path);
179 
180  void open_split(const std::string& path);
181 
182  void close_segment();
183 
184  bool merge_schema(SchemaData& schema_data);
185 
186  bool load_schema(const std::string& ser_type, SchemaType& schema_type, SchemaData& schema_data);
187 
188  bool write(const std::string& url, const std::string& ser_type, SchemaType schema_type, ActionType action_type,
189  const Bytes& data, int64_t microseconds_timestamp);
190 
191  bool write_filex(bool complete = true);
192 
193  struct Impl;
194  std::unique_ptr<Impl> impl_;
195 
197 };
198 
199 } // namespace vlink
Abstract VLink bag recorder with split, compression, schema embedding and a global hook.
#define VLINK_EXPORT
Definition: macros.h:81
#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
Deletes the copy constructor and copy-assignment operator of classname.
Definition: macros.h:174