Branch data Line data Source code
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 : : #include "./extension/bag_reader.h"
25 : :
26 : : #include <algorithm>
27 : : #include <memory>
28 : : #include <shared_mutex>
29 : : #include <string>
30 : : #include <unordered_map>
31 : : #include <unordered_set>
32 : : #include <utility>
33 : :
34 : : #include "./base/helpers.h"
35 : : #include "./base/logger.h"
36 : : #include "./extension/bag_plugin_interface.h"
37 : : #include "./extension/vcap_reader.h"
38 : : #include "./extension/vdb_reader.h"
39 : : #include "./impl/url.h"
40 : :
41 : : namespace vlink {
42 : :
43 : : // UrlMeta
44 : 227 : bool BagReader::Info::UrlMeta::operator<(const BagReader::Info::UrlMeta& target) const noexcept {
45 : 227 : int lindex = Url::get_sort_index(url);
46 : 227 : int rindex = Url::get_sort_index(target.url);
47 : :
48 [ + + ]: 227 : if (lindex < rindex) {
49 : 1 : return true;
50 [ + + ]: 226 : } else if (lindex > rindex) {
51 : 3 : return false;
52 [ + + ]: 223 : } else if (url < target.url) {
53 : 20 : return true;
54 [ + + ]: 203 : } else if (url > target.url) {
55 : 192 : return false;
56 : : }
57 : :
58 : 11 : return index < target.index;
59 : : }
60 : :
61 : : // BagReader::Impl
62 : : struct BagReader::Impl final {
63 : : BagReader::OutputCallback output_callback;
64 : : std::shared_ptr<BagPluginInterface> plugin_interface;
65 : : std::unordered_map<std::string, std::string> playback_url_remap;
66 : : std::unordered_set<std::string> excluded_playback_urls;
67 : : std::unordered_map<std::string, std::string> url_to_ser_map;
68 : : std::unordered_map<std::string, SchemaType> url_to_schema_type_map;
69 : : std::atomic_bool playback_url_rules_enabled{false};
70 : : mutable std::shared_mutex playback_state_mtx;
71 : : mutable std::shared_mutex output_callback_mtx;
72 : :
73 : : bool cursor_opened{false};
74 : : bool cursor_eof{false};
75 : : bool cursor_fail{false};
76 : : };
77 : :
78 : : // BagReader
79 : 407 : std::shared_ptr<BagReader> BagReader::create(const std::string& path, bool read_only, bool try_to_fix) {
80 [ + - ]: 407 : std::string suffix_check = path;
81 : :
82 : 407 : std::transform(suffix_check.begin(), suffix_check.end(), suffix_check.begin(),
83 : 32736 : [](unsigned char c) { return std::tolower(c); });
84 : :
85 [ + + + + : 407 : if (Helpers::has_endwith(suffix_check, ".vdb") || Helpers::has_endwith(suffix_check, ".vdbx")) {
+ + ]
86 [ + + ]: 221 : return std::make_shared<VDBReader>(path, read_only, try_to_fix);
87 [ + + + + : 186 : } else if (Helpers::has_endwith(suffix_check, ".vcap") || Helpers::has_endwith(suffix_check, ".vcapx")) {
+ + ]
88 [ + + ]: 185 : return std::make_shared<VCAPReader>(path, read_only, try_to_fix);
89 : : } else {
90 [ + - + - : 2 : CLOG_E("BagReader: Unknown bag suffix, path=%s", path.c_str());
+ - ]
91 : 1 : return nullptr;
92 : : }
93 : 407 : }
94 : :
95 [ + - ]: 425 : BagReader::BagReader(const std::string& path, bool read_only, bool try_to_fix) : impl_(std::make_unique<Impl>()) {
96 : : (void)path;
97 : : (void)read_only;
98 : : (void)try_to_fix;
99 : :
100 : 425 : Bytes::init_memory_pool();
101 : 425 : }
102 : :
103 : 425 : BagReader::~BagReader() {
104 : 425 : std::shared_ptr<BagPluginInterface> plugin_interface;
105 : :
106 : : {
107 : 425 : std::shared_lock state_lock(impl_->playback_state_mtx);
108 : 425 : plugin_interface = impl_->plugin_interface;
109 : 425 : }
110 : :
111 [ + + ]: 425 : if (plugin_interface) {
112 : 9 : plugin_interface->register_callback({});
113 : : }
114 : 425 : }
115 : :
116 : 26 : void BagReader::bind_bag_interface(const std::shared_ptr<BagPluginInterface>& bag_interface) {
117 : 26 : std::shared_ptr<BagPluginInterface> old_plugin_interface;
118 : :
119 : : {
120 [ + - ]: 26 : std::shared_lock state_lock(impl_->playback_state_mtx);
121 : 26 : old_plugin_interface = impl_->plugin_interface;
122 : 26 : }
123 : :
124 [ + + + - : 26 : if (old_plugin_interface && old_plugin_interface != bag_interface) {
+ + ]
125 [ + - ]: 3 : old_plugin_interface->flush();
126 : 3 : old_plugin_interface->register_callback({});
127 : : }
128 : :
129 [ + + ]: 26 : if VLIKELY (bag_interface) {
130 : 24 : bag_interface->bind_direction(BagPluginInterface::Direction::kRead);
131 : :
132 [ + - ]: 24 : bag_interface->register_callback([this](const Frame& frame) {
133 : 36 : std::string output_url;
134 : :
135 [ + - - + ]: 36 : if VUNLIKELY (!convert_playback_url(frame.url, output_url)) {
136 : : return; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
137 : : }
138 : :
139 [ + - ]: 36 : std::shared_lock callback_lock(impl_->output_callback_mtx);
140 : :
141 [ + - ]: 36 : if VLIKELY (impl_->output_callback) {
142 : 36 : Frame out;
143 : 36 : out.timestamp = frame.timestamp;
144 : 36 : out.url = std::move(output_url);
145 [ + - ]: 36 : out.ser_type = frame.ser_type;
146 : 36 : out.schema_type = frame.schema_type;
147 : 36 : out.action_type = frame.action_type;
148 : 36 : out.data = Bytes::shallow_copy(frame.data.data(), frame.data.size());
149 : :
150 [ + + - + : 36 : if (out.ser_type.empty() || out.schema_type == SchemaType::kUnknown) {
+ + ]
151 [ + - ]: 6 : fill_frame_meta(out);
152 : : }
153 : :
154 [ + - ]: 36 : impl_->output_callback(out);
155 : 36 : }
156 [ + - ]: 36 : });
157 : : }
158 : :
159 [ + - ]: 26 : std::unique_lock state_lock(impl_->playback_state_mtx);
160 : :
161 : 26 : impl_->plugin_interface = bag_interface;
162 : 26 : impl_->playback_url_remap.clear();
163 : 26 : impl_->excluded_playback_urls.clear();
164 : 26 : impl_->playback_url_rules_enabled.store(false, std::memory_order_release);
165 : 26 : }
166 : :
167 [ # # ]: 0 : void BagReader::clear_bag_interface() { bind_bag_interface(nullptr); }
168 : :
169 : 1 : void BagReader::register_status_callback(StatusCallback&& status_callback) { (void)status_callback; }
170 : :
171 : 1 : void BagReader::register_ready_callback(ReadyCallback&& ready_callback) { (void)ready_callback; }
172 : :
173 : 1 : void BagReader::register_finish_callback(FinishCallback&& finish_callback) { (void)finish_callback; }
174 : :
175 : 40 : void BagReader::register_output_callback(OutputCallback&& output_callback) {
176 [ + - ]: 40 : std::unique_lock lock(impl_->output_callback_mtx);
177 : :
178 : 40 : impl_->output_callback = std::move(output_callback);
179 : 40 : }
180 : :
181 : 233 : bool BagReader::open_cursor(const Config& config) {
182 : 233 : impl_->cursor_opened = false;
183 : 233 : impl_->cursor_eof = false;
184 : 233 : impl_->cursor_fail = false;
185 : :
186 [ + + ]: 233 : if VUNLIKELY (!do_open_cursor(config)) {
187 : 2 : impl_->cursor_fail = true;
188 : 2 : return false;
189 : : }
190 : :
191 : 231 : impl_->cursor_opened = true;
192 : 231 : return true;
193 : : }
194 : :
195 [ + - ]: 193 : bool BagReader::open_cursor() { return open_cursor(Config{}); }
196 : :
197 : 1173 : bool BagReader::read_next(Frame& out) {
198 [ + + ]: 1173 : if VUNLIKELY (impl_->cursor_fail) {
199 : 2 : return false;
200 : : }
201 : :
202 [ + + ]: 1171 : if VUNLIKELY (impl_->cursor_eof) {
203 : 1 : return false;
204 : : }
205 : :
206 [ + + + - : 1170 : if (!impl_->cursor_opened && !open_cursor(Config{})) {
- + + + -
+ - - ]
207 : : return false; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
208 : : }
209 : :
210 : 1170 : bool is_error = false;
211 : :
212 [ + - + + ]: 1170 : if VLIKELY (do_read_next(out, is_error)) {
213 : 939 : return true;
214 : : }
215 : :
216 [ - + ]: 231 : if (is_error) {
217 : : impl_->cursor_fail = true; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
218 : : } else {
219 : 231 : impl_->cursor_eof = true;
220 : : }
221 : :
222 : 231 : return false;
223 : : }
224 : :
225 : 12 : BagReader& BagReader::operator>>(Frame& out) {
226 : 12 : read_next(out);
227 : :
228 : 12 : return *this;
229 : : }
230 : :
231 : 32 : bool BagReader::eof() const noexcept { return impl_->cursor_eof; }
232 : :
233 : 28 : bool BagReader::fail() const noexcept { return impl_->cursor_fail; }
234 : :
235 [ + + + + ]: 14 : BagReader::operator bool() const noexcept { return !impl_->cursor_eof && !impl_->cursor_fail; }
236 : :
237 : 27 : std::string BagReader::get_ser_type(const std::string& url) const {
238 [ + - ]: 27 : std::shared_lock state_lock(impl_->playback_state_mtx);
239 : :
240 [ + - ]: 27 : auto iter = impl_->url_to_ser_map.find(url);
241 : :
242 [ + + ]: 27 : if VLIKELY (iter != impl_->url_to_ser_map.end()) {
243 [ + - ]: 18 : return iter->second;
244 : : }
245 : :
246 : 9 : return {};
247 : 27 : }
248 : :
249 : 15 : SchemaType BagReader::get_schema_type(const std::string& url) const {
250 [ + - ]: 15 : std::shared_lock state_lock(impl_->playback_state_mtx);
251 : :
252 [ + - ]: 15 : auto iter = impl_->url_to_schema_type_map.find(url);
253 : :
254 [ + + ]: 15 : if VLIKELY (iter != impl_->url_to_schema_type_map.end()) {
255 : 12 : return iter->second;
256 : : }
257 : :
258 : 3 : return SchemaType::kUnknown;
259 : 15 : }
260 : :
261 : 1 : bool BagReader::do_open_cursor(const Config& config) {
262 : : (void)config;
263 : :
264 : 1 : return false;
265 : : }
266 : :
267 : : bool BagReader::do_read_next(Frame& out, bool& is_error) { // LCOV_EXCL_LINE GCOVR_EXCL_LINE
268 : : (void)out;
269 : :
270 : : is_error = false; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
271 : :
272 : : return false; // LCOV_EXCL_LINE GCOVR_EXCL_LINE
273 : : }
274 : :
275 : 1920 : void BagReader::rebuild_url_meta_maps(const std::vector<Info::UrlMeta>& url_metas,
276 : : std::unordered_map<std::string, std::string>& ser_map,
277 : : std::unordered_map<std::string, SchemaType>& schema_type_map) {
278 : 1920 : ser_map.clear();
279 : 1920 : schema_type_map.clear();
280 [ + - ]: 1920 : ser_map.reserve(url_metas.size());
281 [ + - ]: 1920 : schema_type_map.reserve(url_metas.size());
282 : :
283 : 1920 : std::unordered_set<std::string> ser_conflict_urls;
284 : 1920 : std::unordered_set<std::string> schema_conflict_urls;
285 : :
286 [ + - ]: 1920 : ser_conflict_urls.reserve(url_metas.size());
287 [ + - ]: 1920 : schema_conflict_urls.reserve(url_metas.size());
288 : :
289 [ + + ]: 3978 : for (const auto& meta : url_metas) {
290 [ + - ]: 2058 : auto& merged_ser_type = ser_map[meta.url];
291 [ + - ]: 2058 : auto& merged_schema_type = schema_type_map[meta.url];
292 : :
293 [ + - + + : 2058 : if (ser_conflict_urls.count(meta.url) == 0U && !meta.ser_type.empty()) {
+ + + + ]
294 [ + + + + : 2039 : if (merged_ser_type.empty() || merged_ser_type == "Bytes") {
+ + ]
295 [ + - ]: 2034 : merged_ser_type = meta.ser_type;
296 [ + - + + : 5 : } else if (meta.ser_type != "Bytes" && meta.ser_type != merged_ser_type) {
+ + ]
297 [ + - + - : 2 : CLOG_E("BagReader: URL remap collision on %s, keeping ser_type unknown. ser [%s] vs [%s].", meta.url.c_str(),
+ - ]
298 : : merged_ser_type.c_str(), meta.ser_type.c_str());
299 : 1 : merged_ser_type.clear();
300 [ + - ]: 1 : ser_conflict_urls.emplace(meta.url);
301 : : }
302 : : }
303 : :
304 [ + - + + : 2058 : if (schema_conflict_urls.count(meta.url) == 0U && meta.schema_type != SchemaType::kUnknown) {
+ + + + ]
305 [ + + ]: 2006 : if (merged_schema_type == SchemaType::kUnknown) {
306 : 2001 : merged_schema_type = meta.schema_type;
307 [ + + ]: 5 : } else if (merged_schema_type != meta.schema_type) {
308 : 1 : const auto current_label = SchemaData::convert_type(merged_schema_type);
309 : 1 : const auto new_label = SchemaData::convert_type(meta.schema_type);
310 [ + - + - : 2 : CLOG_E("BagReader: URL remap collision on %s, keeping schema_type unknown. schema [%.*s] vs [%.*s].",
+ - ]
311 : : meta.url.c_str(), static_cast<int>(current_label.size()), current_label.data(),
312 : : static_cast<int>(new_label.size()), new_label.data());
313 : 1 : merged_schema_type = SchemaType::kUnknown;
314 [ + - ]: 1 : schema_conflict_urls.emplace(meta.url);
315 : : }
316 : : }
317 : : }
318 : 1920 : }
319 : :
320 : 189 : void BagReader::process_output(Frame& frame) {
321 : 189 : std::shared_ptr<BagPluginInterface> plugin_interface;
322 : :
323 : : {
324 [ + - ]: 189 : std::shared_lock state_lock(impl_->playback_state_mtx);
325 : :
326 : 189 : plugin_interface = impl_->plugin_interface;
327 : :
328 [ + + + - : 189 : if VUNLIKELY (plugin_interface && impl_->excluded_playback_urls.count(frame.url) != 0U) {
+ + + + ]
329 : 1 : return;
330 : : }
331 : :
332 : 188 : const std::string* meta_url = &frame.url;
333 : :
334 [ + + ]: 188 : if (plugin_interface) {
335 [ + - ]: 47 : auto remap_iter = impl_->playback_url_remap.find(frame.url);
336 : :
337 [ + + ]: 47 : if (remap_iter != impl_->playback_url_remap.end()) {
338 : 2 : meta_url = &remap_iter->second;
339 : : }
340 : : }
341 : :
342 [ + - ]: 188 : if (frame.ser_type.empty()) {
343 [ + - ]: 188 : auto ser_iter = impl_->url_to_ser_map.find(*meta_url);
344 : :
345 [ + + ]: 188 : if VLIKELY (ser_iter != impl_->url_to_ser_map.end()) {
346 [ + - ]: 182 : frame.ser_type = ser_iter->second;
347 : : }
348 : : }
349 : :
350 [ + - ]: 188 : if (frame.schema_type == SchemaType::kUnknown) {
351 [ + - ]: 188 : auto schema_iter = impl_->url_to_schema_type_map.find(*meta_url);
352 : :
353 [ + + ]: 188 : if VLIKELY (schema_iter != impl_->url_to_schema_type_map.end()) {
354 : 182 : frame.schema_type = schema_iter->second;
355 : : }
356 : : }
357 [ + + ]: 189 : }
358 : :
359 [ + + ]: 188 : if (plugin_interface) {
360 [ + - ]: 47 : plugin_interface->on_read(frame);
361 : : } else {
362 [ + - ]: 141 : std::shared_lock callback_lock(impl_->output_callback_mtx);
363 : :
364 [ + + ]: 141 : if VLIKELY (impl_->output_callback) {
365 [ + - ]: 140 : impl_->output_callback(frame);
366 : : }
367 : 141 : }
368 [ + + ]: 189 : }
369 : :
370 : 937 : void BagReader::fill_frame_meta(Frame& frame) const {
371 [ + - ]: 937 : std::shared_lock state_lock(impl_->playback_state_mtx);
372 : :
373 [ + - ]: 937 : if (frame.ser_type.empty()) {
374 [ + - ]: 937 : auto iter = impl_->url_to_ser_map.find(frame.url);
375 : :
376 [ + + ]: 937 : if VLIKELY (iter != impl_->url_to_ser_map.end()) {
377 [ + - ]: 932 : frame.ser_type = iter->second;
378 : : }
379 : : }
380 : :
381 [ + - ]: 937 : if (frame.schema_type == SchemaType::kUnknown) {
382 [ + - ]: 937 : auto iter = impl_->url_to_schema_type_map.find(frame.url);
383 : :
384 [ + + ]: 937 : if VLIKELY (iter != impl_->url_to_schema_type_map.end()) {
385 : 932 : frame.schema_type = iter->second;
386 : : }
387 : : }
388 : 937 : }
389 : :
390 : 71 : void BagReader::reset_plugin() {
391 : 71 : std::shared_ptr<BagPluginInterface> plugin_interface;
392 : :
393 : : {
394 [ + - ]: 71 : std::shared_lock state_lock(impl_->playback_state_mtx);
395 : 71 : plugin_interface = impl_->plugin_interface;
396 : 71 : }
397 : :
398 [ + + ]: 71 : if (plugin_interface) {
399 [ + - ]: 18 : plugin_interface->on_reset();
400 : : }
401 : 71 : }
402 : :
403 : 58 : void BagReader::flush_plugin() {
404 : 58 : std::shared_ptr<BagPluginInterface> plugin_interface;
405 : :
406 : : {
407 [ + - ]: 58 : std::shared_lock state_lock(impl_->playback_state_mtx);
408 : 58 : plugin_interface = impl_->plugin_interface;
409 : 58 : }
410 : :
411 [ + + ]: 58 : if (plugin_interface) {
412 [ + - ]: 13 : plugin_interface->flush();
413 : : }
414 : 58 : }
415 : :
416 : 24 : void BagReader::process_url_metas(std::vector<Info::UrlMeta>& url_metas) {
417 : 24 : std::shared_ptr<BagPluginInterface> plugin_interface;
418 : :
419 : : {
420 [ + - ]: 24 : std::shared_lock state_lock(impl_->playback_state_mtx);
421 : 24 : plugin_interface = impl_->plugin_interface;
422 : 24 : }
423 : :
424 : 24 : std::unordered_map<std::string, std::string> playback_url_remap;
425 : 24 : std::unordered_set<std::string> excluded_playback_urls;
426 : :
427 [ + + ]: 24 : if (plugin_interface) {
428 [ + - ]: 42 : url_metas.erase(
429 [ + - ]: 21 : std::remove_if(url_metas.begin(), url_metas.end(),
430 : 103 : [&plugin_interface, &playback_url_remap, &excluded_playback_urls](Info::UrlMeta& meta) {
431 [ + - ]: 45 : const std::string input_url = meta.url;
432 : :
433 [ + - + + ]: 45 : if VUNLIKELY (!plugin_interface->convert_url_meta(meta.url, meta.ser_type, meta.schema_type)) {
434 [ + - ]: 5 : excluded_playback_urls.emplace(input_url);
435 : 5 : return true;
436 : : }
437 : :
438 [ + + ]: 40 : if (meta.url != input_url) {
439 [ + - + - ]: 8 : playback_url_remap[input_url] = meta.url;
440 : : }
441 : :
442 : 40 : return false;
443 : 45 : }),
444 : 42 : url_metas.end());
445 : : }
446 : :
447 : : {
448 [ + - ]: 24 : std::unique_lock state_lock(impl_->playback_state_mtx);
449 : :
450 [ + - ]: 24 : if (impl_->plugin_interface == plugin_interface) {
451 : 24 : impl_->playback_url_remap = std::move(playback_url_remap);
452 : 24 : impl_->excluded_playback_urls = std::move(excluded_playback_urls);
453 : 48 : impl_->playback_url_rules_enabled.store(
454 [ + + + + ]: 24 : !impl_->playback_url_remap.empty() || !impl_->excluded_playback_urls.empty(), std::memory_order_release);
455 : : }
456 : 24 : }
457 : 24 : }
458 : :
459 : 1918 : void BagReader::rebuild_url_meta_lookup(const std::vector<Info::UrlMeta>& url_metas) {
460 [ + - ]: 1918 : std::unique_lock state_lock(impl_->playback_state_mtx);
461 : :
462 [ + - ]: 1918 : rebuild_url_meta_maps(url_metas, impl_->url_to_ser_map, impl_->url_to_schema_type_map);
463 : 1918 : }
464 : :
465 : 4311 : std::unordered_map<std::string, std::string>& BagReader::url_ser_map() { return impl_->url_to_ser_map; }
466 : :
467 : 4311 : std::unordered_map<std::string, SchemaType>& BagReader::url_schema_type_map() { return impl_->url_to_schema_type_map; }
468 : :
469 : 1042 : bool BagReader::convert_playback_url(const std::string& input_url, std::string& output_url) const {
470 [ + - ]: 1042 : std::shared_lock state_lock(impl_->playback_state_mtx);
471 : :
472 [ + - + + ]: 1042 : if VUNLIKELY (impl_->excluded_playback_urls.count(input_url) != 0U) {
473 : 4 : return false;
474 : : }
475 : :
476 [ + - ]: 1038 : auto iter = impl_->playback_url_remap.find(input_url);
477 : :
478 [ + + ]: 1038 : if (iter != impl_->playback_url_remap.end()) {
479 [ + - ]: 10 : output_url = iter->second;
480 : : } else {
481 [ + - ]: 1028 : output_url = input_url;
482 : : }
483 : :
484 : 1038 : return true;
485 : 1042 : }
486 : :
487 : 162 : bool BagReader::match_playback_url_filter(std::string_view input_url,
488 : : const std::unordered_set<std::string>& filter_urls) const {
489 [ + + ]: 162 : if VUNLIKELY (!input_url.data()) {
490 : 1 : return false;
491 : : }
492 : :
493 [ + + + + : 161 : if (filter_urls.empty() && !has_playback_url_rules()) {
+ + ]
494 : 87 : return true;
495 : : }
496 : :
497 : 74 : std::string output_url;
498 : :
499 [ + - + - : 74 : if VUNLIKELY (!convert_playback_url(std::string(input_url), output_url)) {
+ + ]
500 : 3 : return false;
501 : : }
502 : :
503 [ + + + - : 71 : return filter_urls.empty() || filter_urls.count(output_url) != 0U;
+ + ]
504 : 74 : }
505 : :
506 : 554 : bool BagReader::has_playback_url_rules() const noexcept {
507 : 554 : return impl_->playback_url_rules_enabled.load(std::memory_order_acquire);
508 : : }
509 : :
510 : 1536 : ActionType BagReader::convert_action(std::string_view str) {
511 [ + + ]: 1536 : if (str == "C/Req") {
512 : 28 : return ActionType::kClientRequest;
513 [ + + ]: 1508 : } else if (str == "C/Resp") {
514 : 4 : return ActionType::kClientResponse;
515 [ + + ]: 1504 : } else if (str == "S/Req") {
516 : 3 : return ActionType::kServerRequest;
517 [ + + ]: 1501 : } else if (str == "S/Resp") {
518 : 3 : return ActionType::kServerResponse;
519 [ + + ]: 1498 : } else if (str == "Pub") {
520 : 1423 : return ActionType::kPublish;
521 [ + + ]: 75 : } else if (str == "Sub") {
522 : 20 : return ActionType::kSubscribe;
523 [ + + ]: 55 : } else if (str == "Set") {
524 : 32 : return ActionType::kSet;
525 [ + + ]: 23 : } else if (str == "Get") {
526 : 16 : return ActionType::kGet;
527 : : } else {
528 : 7 : return ActionType::kUnknownAction;
529 : : }
530 : : }
531 : :
532 : 389 : void BagReader::detach_plugin() {
533 : 389 : std::shared_ptr<BagPluginInterface> plugin_interface;
534 : :
535 : : {
536 [ + - ]: 389 : std::unique_lock state_lock(impl_->playback_state_mtx);
537 : 389 : plugin_interface = std::move(impl_->plugin_interface);
538 : 389 : }
539 : :
540 [ + + ]: 389 : if (plugin_interface) {
541 [ + - ]: 12 : plugin_interface->flush();
542 : 12 : plugin_interface->register_callback({});
543 : : }
544 : 389 : }
545 : :
546 : : } // namespace vlink
|