MCPcopy Create free account
hub / github.com/PlotJuggler/PlotJuggler / ensureTopic

Method ensureTopic

pj_datastore/src/plugin_data_host.cpp:386–450  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

384 }
385
386 [[nodiscard]] bool ensureTopic(DataSourceHandle source, std::string_view topic_name, TopicHandle* out_topic) {
387 // Normalize "//""/" once, at the ingest boundary, so the stored topic name,
388 // the catalog and the by-name transform resolver all key off the same string.
389 std::string topic_name_normalized;
390 if (needsSlashNormalization(topic_name)) {
391 topic_name_normalized = normalizeSlashes(topic_name);
392 topic_name = topic_name_normalized;
393 }
394 auto engine_locks = lockWriteEngines(engine, secondary_engine);
395 const auto* dataset = engine.getDataset(source.id);
396 if (dataset == nullptr) {
397 setError(fmt::format("data source {} not found", source.id));
398 return false;
399 }
400
401 DatasetTopicKey key{.dataset_id = source.id, .topic_name = std::string(topic_name)};
402 if (auto it = topic_cache.find(key); it != topic_cache.end()) {
403 // Cache hit — but the secondary may still be missing this topic if a
404 // prior mirror failed; retry. No-op if already mirrored.
405 if (!mirrorTopicToSecondary(source.id, it->second.id, topic_name)) {
406 return false;
407 }
408 *out_topic = it->second;
409 last_error.clear();
410 return true;
411 }
412
413 auto topic_ids = engine.listTopics(source.id);
414 std::sort(topic_ids.begin(), topic_ids.end());
415 for (TopicId tid : topic_ids) {
416 const auto* storage = engine.getTopicStorage(tid);
417 if (storage != nullptr && storage->descriptor().name == topic_name) {
418 // Found in primary — same retry semantics on the secondary.
419 if (!mirrorTopicToSecondary(source.id, tid, topic_name)) {
420 return false;
421 }
422 *out_topic = TopicHandle{.id = tid};
423 topic_cache.emplace(std::move(key), *out_topic);
424 last_error.clear();
425 return true;
426 }
427 }
428
429 TopicDescriptor desc;
430 desc.name = std::string(topic_name);
431 desc.schema_id = 0;
432 auto tid_or = writer.registerTopic(source.id, std::move(desc));
433 if (!tid_or.has_value()) {
434 setError(tid_or.error());
435 return false;
436 }
437
438 // Lockstep mirror to the secondary engine (streaming two-engine model).
439 // Forces the same TopicId on both sides so a later setTarget(secondary)
440 // swap finds the topic that the plugin's cached TopicHandle refers to.
441 // See DataEngine::createTopicField for the field-level counterpart.
442 if (!mirrorTopicToSecondary(source.id, *tid_or, topic_name)) {
443 return false;

Callers 11

TEST_FFunction · 0.80
TEST_FFunction · 0.80
sourceEnsureTopicFunction · 0.80
toolboxEnsureTopicFunction · 0.80
TESTFunction · 0.80
TESTFunction · 0.80
TESTFunction · 0.80
TESTFunction · 0.80
TESTFunction · 0.80
TESTFunction · 0.80
importDataMethod · 0.80

Calls 12

needsSlashNormalizationFunction · 0.85
normalizeSlashesFunction · 0.85
lockWriteEnginesFunction · 0.85
getDatasetMethod · 0.80
getTopicStorageMethod · 0.80
descriptorMethod · 0.80
findMethod · 0.45
endMethod · 0.45
clearMethod · 0.45
listTopicsMethod · 0.45
beginMethod · 0.45
registerTopicMethod · 0.45

Tested by 9

TEST_FFunction · 0.64
TEST_FFunction · 0.64
TESTFunction · 0.64
TESTFunction · 0.64
TESTFunction · 0.64
TESTFunction · 0.64
TESTFunction · 0.64
TESTFunction · 0.64
importDataMethod · 0.64