VLink  2.1.0
A high-performance communication middleware
vdb_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 vdb_writer.h
26  * @brief SQLite-backed recorder that produces @c .vdb / @c .vdbx bag files with batched WAL commits.
27  *
28  * @details
29  * @c VDBWriter materialises @c BagWriter on top of SQLite. Messages are accumulated in an
30  * in-memory cache and flushed to disk in WAL-mode transactions so that the write amplification
31  * remains bounded even at high publish rates; outstanding writes are committed during @c close()
32  * and an optional @c VACUUM step compacts the file on exit.
33  *
34  * @par VDB schema
35  *
36  * | Table | Purpose |
37  * | ----------- | ------------------------------------------------------------------- |
38  * | @c messages | (id, url_id, ts_us, action, data) -- one row per recorded message |
39  * | @c urls | (id, url, ser_type, schema_type) -- topic dictionary |
40  * | @c schemas | (id, ser_type, schema_type, blob) -- embedded schema descriptors |
41  * | @c metadata | (key, value) -- tag, machine name, vlink version, capture time |
42  * | @c stats | (url_id, count, bytes, loss) -- per-URL aggregates updated on flush |
43  *
44  * @par Writer states
45  * @code
46  * +----------+ on_begin() +---------+ push()/push_schema() +-----------+
47  * | closed | -----------------> | opening | -----------------------> | recording |
48  * +----------+ +---------+ +-----------+
49  * ^ |
50  * | v cache full / split
51  * | +------------+
52  * | | committing |
53  * | | WAL flush |
54  * | +------------+
55  * | |
56  * +-------------------- close() / dtor ------------------------ finalising
57  * |
58  * v
59  * (optional)
60  * vacuum
61  * @endcode
62  *
63  * @par Example
64  * @code
65  * vlink::BagWriter::Config cfg;
66  * cfg.compress = vlink::BagWriter::kCompressLzav;
67  * cfg.wal_mode = true;
68  *
69  * auto writer = vlink::BagWriter::create("/data/recording.vdb", cfg);
70  *
71  * writer->async_run();
72  *
73  * vlink::Frame frame;
74  * frame.timestamp = -1; // < 0 => writer auto-assigns from its clock (0 is recorded verbatim)
75  * frame.url = "dds://lidar/front";
76  * frame.ser_type = "demo.proto.PointCloud";
77  * frame.schema_type = vlink::SchemaType::kProtobuf;
78  * frame.action_type = vlink::ActionType::kPublish;
79  * frame.data = serialized_bytes;
80  * writer->push(frame);
81  *
82  * writer->wait_for_idle();
83  * writer->quit();
84  * writer->wait_for_quit();
85  * writer->close();
86  * @endcode
87  *
88  * @see BagWriter, VCAPWriter
89  */
90 
91 #pragma once
92 
93 #include <memory>
94 #include <string>
95 
96 #include "./bag_writer.h"
97 
98 namespace vlink {
99 
100 /**
101  * @class VDBWriter
102  * @brief Concrete SQLite-backed @c BagWriter implementation with WAL caching and batch commits.
103  *
104  * @details
105  * Prefer @c BagWriter::create() for format-agnostic instantiation; instantiate this class
106  * directly only when a SQLite-specific feature is required.
107  */
108 class VLINK_EXPORT VDBWriter final : public BagWriter {
109  public:
110  /**
111  * @brief Opens or creates a SQLite bag file for recording.
112  *
113  * @param path Filesystem path of the @c .vdb or @c .vdbx target.
114  * @param config Recording configuration (split policy, compression, cache thresholds).
115  */
116  explicit VDBWriter(const std::string& path, const Config& config = {});
117 
118  /**
119  * @brief Commits any cached writes and closes the SQLite database.
120  */
121  ~VDBWriter() override;
122 
123  /**
124  * @brief Commits the trailing batch, writes the final metadata and closes the database; idempotent.
125  */
126  void close() override;
127 
128  /**
129  * @brief Registers a callback invoked at each file-split boundary.
130  *
131  * @param callback Receives (split_index, filename) before or after the split.
132  * @param before @c true fires before the new file is opened; @c false fires after.
133  */
134  void register_split_callback(SplitCallback&& callback, bool before) override;
135 
136  /**
137  * @brief Registers a resolver that maps a serialisation-type string to @c SchemaData.
138  *
139  * @param callback Function consulted before inserting a URL row.
140  */
141  void register_schema_callback(SchemaCallback&& callback) override;
142 
143  /**
144  * @brief Embeds @p schema_data in the @c schemas table for offline introspection.
145  *
146  * @param schema_data Schema descriptor to embed.
147  * @return @c false when a synchronous merge fails or an asynchronous merge cannot be queued.
148  */
149  bool push_schema(const SchemaData& schema_data) override;
150 
151  /**
152  * @brief Returns the current value of the internal dumping flag.
153  *
154  * @return @c true while messages are actively being persisted.
155  */
156  [[nodiscard]] bool is_dumping() const override;
157 
158  /**
159  * @brief Reports whether split-file recording is active.
160  *
161  * @return @c true when emitting a @c .vdbx manifest with multiple parts.
162  */
163  [[nodiscard]] bool is_split_mode() const override;
164 
165  /**
166  * @brief Returns the index of the split part currently being written.
167  *
168  * @return Zero-based split index.
169  */
170  [[nodiscard]] int get_split_index() const override;
171 
172  protected:
173  int64_t record(const Frame& frame, int64_t timestamp) override;
174 
175  int64_t get_record_timestamp() const override;
176 
177  size_t get_max_task_count() const override;
178 
179  void on_begin() override;
180 
181  void on_end() override;
182 
183  private:
184  void open(const std::string& path);
185 
186  void open_split(const std::string& path);
187 
188  void close_segment();
189 
190  bool write(const std::string& url, const std::string& ser_type, SchemaType schema_type, ActionType action_type,
191  const Bytes& data, int64_t microseconds_timestamp);
192 
193  bool write_filex(bool complete = true);
194 
195  bool begin_cache();
196 
197  bool sync_cache();
198 
199  bool rollback_cache();
200 
201  bool merge_schema(SchemaData& schema_data);
202 
203  bool load_schema(const std::string& ser_type, SchemaType& schema_type, SchemaData& schema_data);
204 
205  bool insert_schema(const SchemaData& schema_data);
206 
207  struct Impl;
208  std::unique_ptr<Impl> impl_;
209 
211 };
212 
213 } // 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