Project
Loading...
Searching...
No Matches
DataSpecUtils.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
17
18#include <fmt/base.h>
19#include <fmt/format.h>
20#include <sstream>
21#include <cstring>
22#include <cinttypes>
23#include <regex>
24#include <stdexcept>
25
26namespace o2::framework
27{
28
29namespace
30{
31std::string join(ConcreteDataMatcher const& matcher, std::string const& sep = "_")
32{
33 return matcher.origin.as<std::string>() + sep + matcher.description.as<std::string>() + sep + std::to_string(matcher.subSpec);
34}
35
36std::string join(ConcreteDataTypeMatcher const& matcher, std::string const& sep = "_")
37{
38 return matcher.origin.as<std::string>() + sep + matcher.description.as<std::string>();
39}
40} // namespace
41
42using namespace data_matcher;
43
45 const o2::header::DataOrigin& origin,
46 const o2::header::DataDescription& description,
48{
49 ConcreteDataMatcher target{origin, description, subSpec};
50 return match(spec, target);
51}
52
54 const o2::header::DataOrigin& origin,
55 const o2::header::DataDescription& description,
57{
59
60 return std::visit(overloaded{[&dataType, &origin, &description, &subSpec](ConcreteDataMatcher const& matcher) -> bool {
61 return dataType.origin == origin &&
62 dataType.description == description &&
63 matcher.subSpec == subSpec;
64 },
65 [&dataType, &origin, &description](ConcreteDataTypeMatcher const& matcher) {
66 return dataType.origin == origin &&
67 dataType.description == description;
68 }},
69 spec.matcher);
70}
71
72std::string DataSpecUtils::describe(InputSpec const& spec)
73{
74 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
75 return join(*concrete, "/");
76 } else if (auto matcher = std::get_if<DataDescriptorMatcher>(&spec.matcher)) {
77 std::ostringstream ss;
78 ss << "<matcher query: " << *matcher << ">";
79 return ss.str();
80 }
81 throw runtime_error("Unhandled InputSpec kind.");
82}
83
84std::string DataSpecUtils::describe(OutputSpec const& spec)
85{
86 return std::visit([](auto const& concrete) {
87 return join(concrete, "/");
88 },
89 spec.matcher);
90}
91
92template <HasMatcher T>
93size_t DataSpecUtils::describe(char* buffer, size_t size, T const& spec)
94{
95 auto result = std::visit(overloaded{
96 [buffer, size](ConcreteDataMatcher const& concrete) -> fmt::format_to_n_result<char*> {
97 return fmt::format_to_n(buffer, size - 1, "{:.4}/{:.16}/{}", concrete.origin.str, concrete.description.str, concrete.subSpec);
98 },
99 [buffer, size](ConcreteDataTypeMatcher const& concrete) -> fmt::format_to_n_result<char*> {
100 return fmt::format_to_n(buffer, size - 1, "<matcher query: {}/{}>", concrete.origin, concrete.description);
101 },
102 [buffer, size](DataDescriptorMatcher const& matcher) -> fmt::format_to_n_result<char*> {
103 std::ostringstream ss;
104 ss << "<matcher query: " << matcher << ">";
105 return fmt::format_to_n(buffer, size - 1, "{}", ss.str());
106 },
107 [](...) -> fmt::format_to_n_result<char*> { throw std::runtime_error("Unsupported Input / Output Spec"); }},
108 spec.matcher);
109 *result.out = '\0';
110 return result.out - buffer;
111}
112
113template size_t DataSpecUtils::describe(char* buffer, size_t size, InputSpec const& spec);
114template size_t DataSpecUtils::describe(char* buffer, size_t size, OutputSpec const& spec);
115
116std::string DataSpecUtils::label(InputSpec const& spec)
117{
118 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
119 return join(*concrete, "_");
120 } else if (auto matcher = std::get_if<DataDescriptorMatcher>(&spec.matcher)) {
121 std::ostringstream ss;
122 ss << *matcher;
123 std::hash<std::string> hash_fn;
124 auto s = ss.str();
125 auto result = std::to_string(hash_fn(s));
126
127 return result;
128 }
129 throw runtime_error("Unsupported InputSpec");
130}
131
132std::string DataSpecUtils::label(OutputSpec const& spec)
133{
134 // FIXME: unite with the InputSpec one...
135 return std::visit(overloaded{[](auto const& matcher) {
136 return join(matcher, "_");
137 }},
138 spec.matcher);
139}
140
142{
143 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
144 return std::string("/") + join(*concrete, "/");
145 } else {
146 throw runtime_error("Unsupported InputSpec kind");
147 }
148}
149
151{
152 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
153 concrete->subSpec = subSpec;
154 } else {
155 // FIXME: this will only work for the cases in which we do have a dataType defined.
156 auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec);
157 spec.matcher = ConcreteDataMatcher(dataType.origin, dataType.description, subSpec);
158 }
159}
160
162{
163 std::visit(overloaded{
164 [&subSpec](ConcreteDataMatcher& concrete) {
165 concrete.subSpec = subSpec;
166 },
167 [&spec, &subSpec](ConcreteDataTypeMatcher& dataType) {
169 dataType.origin,
170 dataType.description,
171 subSpec};
172 },
173 },
174 spec.matcher);
175}
176
178{
179 using namespace header;
180 if (spec.binding.empty()) {
181 return false;
182 }
183 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
184 return (concrete->description != DataDescription("")) &&
185 (concrete->description != header::gDataDescriptionInvalid) &&
186 (concrete->origin != DataOrigin("")) &&
187 (concrete->origin != header::gDataOriginInvalid);
188 }
189 return true;
190}
191
193{
194 using namespace header;
195 auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec);
196 return (dataType.description != DataDescription("")) &&
197 (dataType.description != header::gDataDescriptionInvalid) &&
198 (dataType.origin != DataOrigin("")) &&
199 (dataType.origin != header::gDataOriginInvalid);
200}
201
203{
204 return std::visit(overloaded{
205 [](ConcreteDataMatcher const& matcher) {
206 // We return false because the matcher is more
207 // qualified (has subSpec) than the target.
208 return false;
209 },
210 [&target](DataDescriptorMatcher const& matcher) {
211 // FIXME: to do it properly we should actually make sure that the
212 // matcher is invariant for changes of SubSpecification. Maybe it's
213 // enough to check that none of the nodes actually match on SubSpec.
214 ConcreteDataMatcher concreteExample{
216 target.description,
217 static_cast<header::DataHeader::SubSpecificationType>(0xffffffff)};
219 return matcher.match(concreteExample, context);
220 }},
221 spec.matcher);
222}
223
225{
226 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
227 return *concrete == target;
228 } else if (auto matcher = std::get_if<DataDescriptorMatcher>(&spec.matcher)) {
230 return matcher->match(target, context);
231 } else {
232 throw runtime_error("Unsupported InputSpec");
233 }
234}
235
237{
238 return std::visit(overloaded{
239 [&target](ConcreteDataMatcher const& concrete) {
240 return concrete == target;
241 },
242 [&target](ConcreteDataTypeMatcher const& concrete) {
243 return concrete.origin == target.origin &&
244 concrete.description == target.description;
245 }},
246 spec.matcher);
247}
248
250{
251 if (auto leftConcrete = std::get_if<ConcreteDataMatcher>(&left.matcher)) {
252 return match(right, *leftConcrete);
253 } else if (auto rightConcrete = std::get_if<ConcreteDataMatcher>(&right.matcher)) {
254 return match(left, *rightConcrete);
255 } else {
256 // both sides are ConcreteDataTypeMatcher without subspecification, we simply specify 0
257 // this is ignored in the mathing since also left hand object is ConcreteDataTypeMatcher
259 return match(left, dataType.origin, dataType.description, 0);
260 }
261}
262
264{
265 return std::visit([&input](auto const& concrete) -> bool {
266 return DataSpecUtils::match(input, concrete);
267 },
268 output.matcher);
269}
270
272{
274 return dataType.origin == origin;
275}
276
278{
279 return DataSpecUtils::asConcreteOrigin(input) == origin;
280}
281
283{
284 try {
285 return DataSpecUtils::asConcreteDataDescription(input) == description;
286 } catch (...) {
287 return false;
288 }
289}
290
292{
293 try {
295 } catch (...) {
296 return false;
297 }
298}
299
301 header::DataOrigin origin = header::gDataOriginInvalid; // Whether or not we found an origins (should be a bad query!)
302 header::DataDescription description = header::gDataDescriptionInvalid; // Whether or not we found a description
303 header::DataHeader::SubSpecificationType subSpec = 0; // Whether or not we found a description
304 bool hasOrigin = false;
305 bool hasDescription = false;
306 bool hasSubSpec = false;
307 bool hasUniqueOrigin = false; // Whether the matcher involves a unique origin
308 bool hasUniqueDescription = false; // Whether the matcher involves a unique origin
309 bool hasUniqueSubSpec = false;
310 bool hasError = false;
311};
312
314{
315 using namespace data_matcher;
316 using ops = DataDescriptorMatcher::Op;
317
319 auto nodeWalker = overloaded{
320 [&state](EdgeActions::EnterNode action) {
321 if (state.hasError) {
322 return VisitNone;
323 }
324 // For now we do not support extracting a type from things
325 // which have an OR, so we reset all the uniqueness attributes.
326 if (action.node->getOp() == ops::Or || action.node->getOp() == ops::Xor) {
327 state.hasError = true;
328 return VisitNone;
329 }
330 if (action.node->getOp() == ops::Just ||
331 action.node->getOp() == ops::Not) {
332 return VisitLeft;
333 }
334 return VisitBoth;
335 },
336 [](auto) { return VisitNone; }};
337
338 auto leafWalker = overloaded{
339 [&state](OriginValueMatcher const& valueMatcher) {
340 // FIXME: If we found already more than one data origin, it means
341 // we are ANDing two incompatible origins. Until we support OR,
342 // this is an error.
343 // In case we find a ContextRef, it means we have
344 // a wildcard, so there is not a unique origin.
345 if (state.hasOrigin) {
346 state.hasError = false;
347 return;
348 }
349 state.hasOrigin = true;
350
351 valueMatcher.visit(overloaded{
352 [&state](std::string const& s) {
353 strncpy(state.origin.str, s.data(), 4);
354 state.hasUniqueOrigin = true;
355 },
356 [&state](auto) { state.hasUniqueOrigin = false; }});
357 },
358 [&state](DescriptionValueMatcher const& valueMatcher) {
359 if (state.hasDescription) {
360 state.hasError = true;
361 return;
362 }
363 state.hasDescription = true;
364 valueMatcher.visit(overloaded{
365 [&state](std::string const& s) {
366 strncpy(state.description.str, s.data(), 16);
367 state.hasUniqueDescription = true;
368 },
369 [&state](auto) { state.hasUniqueDescription = false; }});
370 },
371 [&state](SubSpecificationTypeValueMatcher const& valueMatcher) {
372 if (state.hasSubSpec) {
373 state.hasError = true;
374 return;
375 }
376 state.hasSubSpec = true;
377 valueMatcher.visit(overloaded{
378 [&state](uint32_t const& data) {
379 state.subSpec = data;
380 state.hasUniqueSubSpec = true;
381 },
382 [&state](auto) { state.hasUniqueSubSpec = false; }});
383 },
384 [](auto t) {}};
385 DataMatcherWalker::walk(top, nodeWalker, leafWalker);
386 return state;
387}
388
390{
391 return std::visit(overloaded{[](ConcreteDataMatcher const& concrete) {
392 return concrete;
393 },
394 [&binding = spec.binding](DataDescriptorMatcher const& matcher) {
395 auto info = extractMatcherInfo(matcher);
396 if (info.hasOrigin && info.hasUniqueOrigin &&
397 info.hasDescription && info.hasDescription &&
398 info.hasSubSpec && info.hasUniqueSubSpec) {
399 return ConcreteDataMatcher{info.origin, info.description, info.subSpec};
400 }
401 throw std::runtime_error("Cannot convert " + binding + " to ConcreteDataMatcher");
402 }},
403 spec.matcher);
404}
405
407{
408 return std::get<ConcreteDataMatcher>(spec.matcher);
409}
410
411std::optional<ConcreteDataMatcher> DataSpecUtils::asOptionalConcreteDataMatcher(OutputSpec const& spec)
412{
413 return std::visit(overloaded{
414 [](ConcreteDataMatcher const& concrete) {
415 return std::optional<ConcreteDataMatcher>{concrete};
416 },
417 [](DataDescriptorMatcher const& matcher) {
419 },
420 [](auto const&) { return std::optional<ConcreteDataMatcher>{std::nullopt}; }},
421 spec.matcher);
422}
423
425{
426 return std::visit([](auto const& concrete) {
427 return ConcreteDataTypeMatcher{concrete.origin, concrete.description};
428 },
429 spec.matcher);
430}
431
433{
434 return std::visit(overloaded{
435 [](auto const& concrete) {
436 return ConcreteDataTypeMatcher{concrete.origin, concrete.description};
437 },
438 [](DataDescriptorMatcher const& matcher) {
439 auto state = extractMatcherInfo(matcher);
440 if (state.hasUniqueOrigin && state.hasUniqueDescription) {
441 return ConcreteDataTypeMatcher{state.origin, state.description};
442 }
443 throw runtime_error("Could not extract data type from query");
444 }},
445 spec.matcher);
446}
447
449{
450 return std::visit(overloaded{
451 [](auto const& concrete) {
452 return concrete.origin;
453 },
454 [](DataDescriptorMatcher const& matcher) {
455 auto state = extractMatcherInfo(matcher);
456 if (state.hasUniqueOrigin) {
457 return state.origin;
458 }
459 throw runtime_error("Could not extract data type from query");
460 }},
461 spec.matcher);
462}
463
465{
466 return std::visit(overloaded{
467 [](auto const& concrete) {
468 return concrete.description;
469 },
470 [](DataDescriptorMatcher const& matcher) {
471 auto state = extractMatcherInfo(matcher);
472 if (state.hasUniqueDescription) {
473 return state.description;
474 }
475 throw runtime_error("Could not extract data type from query");
476 }},
477 spec.matcher);
478}
479
481{
482 return std::visit(overloaded{
483 [&spec](ConcreteDataMatcher const& concrete) {
484 return OutputSpec{{spec.binding}, concrete, spec.lifetime};
485 },
486 [&spec](DataDescriptorMatcher const& matcher) {
487 auto state = extractMatcherInfo(matcher);
488 if (state.hasUniqueOrigin && state.hasUniqueDescription && state.hasUniqueSubSpec) {
489 return OutputSpec{{spec.binding}, ConcreteDataMatcher{state.origin, state.description, state.subSpec}, spec.lifetime};
490 } else if (state.hasUniqueOrigin && state.hasUniqueDescription) {
491 return OutputSpec{{spec.binding}, ConcreteDataTypeMatcher{state.origin, state.description}, spec.lifetime};
492 }
493
494 throw runtime_error_f("Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query %s", describe(spec).c_str());
495 }},
496 spec.matcher);
497}
498
500{
501 DataDescriptorMatcher matchEverything{
502 DataDescriptorMatcher::Op::And,
503 OriginValueMatcher{concrete.origin.as<std::string>()},
504 std::make_unique<DataDescriptorMatcher>(
505 DataDescriptorMatcher::Op::And,
506 DescriptionValueMatcher{concrete.description.as<std::string>()},
507 std::make_unique<DataDescriptorMatcher>(
508 DataDescriptorMatcher::Op::And,
510 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
512 return matchEverything;
513}
514
516{
517 auto timeDescriptionMatcher = std::make_unique<DataDescriptorMatcher>(
518 DataDescriptorMatcher::Op::And,
519 DescriptionValueMatcher{dataType.description.as<std::string>()},
520 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
523 DataDescriptorMatcher::Op::And,
524 OriginValueMatcher{dataType.origin.as<std::string>()},
525 std::move(timeDescriptionMatcher));
526}
527
529{
530 char buf[5] = {0, 0, 0, 0, 0};
531 strncpy(buf, origin.str, 4);
532 DataDescriptorMatcher matchOnlyOrigin{
533 DataDescriptorMatcher::Op::And,
535 std::make_unique<DataDescriptorMatcher>(
536 DataDescriptorMatcher::Op::And,
538 std::make_unique<DataDescriptorMatcher>(
539 DataDescriptorMatcher::Op::And,
541 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
543 return matchOnlyOrigin;
544}
545
547{
548 char buf[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
549 strncpy(buf, description.str, 16);
550 DataDescriptorMatcher matchOnlyOrigin{
551 DataDescriptorMatcher::Op::And,
553 std::make_unique<DataDescriptorMatcher>(
554 DataDescriptorMatcher::Op::And,
556 std::make_unique<DataDescriptorMatcher>(
557 DataDescriptorMatcher::Op::And,
559 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
561 return matchOnlyOrigin;
562}
563
564std::optional<framework::ConcreteDataMatcher> DataSpecUtils::optionalConcreteDataMatcherFrom(data_matcher::DataDescriptorMatcher const& matcher)
565{
566 using namespace data_matcher;
567 using ops = DataDescriptorMatcher::Op;
568
570 auto nodeWalker = overloaded{
571 [&state](EdgeActions::EnterNode action) {
572 if (state.hasError) {
573 return VisitNone;
574 }
575 // a ConcreteDataMatcher requires either 'and' or 'just'
576 // operations and we return the corresponding action for these
577 if (action.node->getOp() == ops::Just) {
578 return VisitLeft;
579 } else if (action.node->getOp() == ops::And) {
580 return VisitBoth;
581 }
582 // simply use the error state to indicate that the operation does not match the
583 // requirement for fully qualified ConcreteDataMatcher
584 state.hasError = true;
585 return VisitNone;
586 },
587 [](auto) { return VisitNone; }};
588
589 auto leafWalker = overloaded{
590 [&state](OriginValueMatcher const& valueMatcher) {
591 // if this is not the first OriginValueMatcher, the value can not be unique
592 if (state.hasOrigin) {
593 state.hasUniqueOrigin = false;
594 return;
595 }
596 state.hasOrigin = true;
597
598 valueMatcher.visit(overloaded{
599 [&state](std::string const& s) {
600 strncpy(state.origin.str, s.data(), 4);
601 state.hasUniqueOrigin = true;
602 },
603 [&state](auto) { state.hasUniqueOrigin = false; }});
604 },
605 [&state](DescriptionValueMatcher const& valueMatcher) {
606 if (state.hasDescription) {
607 state.hasUniqueDescription = false;
608 return;
609 }
610 state.hasDescription = true;
611 valueMatcher.visit(overloaded{
612 [&state](std::string const& s) {
613 strncpy(state.description.str, s.data(), 16);
614 state.hasUniqueDescription = true;
615 },
616 [&state](auto) { state.hasUniqueDescription = false; }});
617 },
618 [&state](SubSpecificationTypeValueMatcher const& valueMatcher) {
619 if (state.hasSubSpec) {
620 state.hasUniqueSubSpec = false;
621 return;
622 }
623 state.hasSubSpec = true;
624 valueMatcher.visit(overloaded{
625 [&state](uint32_t const& data) {
626 state.subSpec = data;
627 state.hasUniqueSubSpec = true;
628 },
629 [&state](auto) { state.hasUniqueSubSpec = false; }});
630 },
631 [](auto t) {}};
632 DataMatcherWalker::walk(matcher, nodeWalker, leafWalker);
633 if (state.hasError == false && state.hasUniqueOrigin && state.hasUniqueDescription && state.hasUniqueSubSpec) {
634 return std::make_optional(ConcreteDataMatcher{state.origin, state.description, state.subSpec});
635 }
636 return {};
637}
638
640{
641 return std::visit(overloaded{
642 [&spec](ConcreteDataMatcher const& concrete) -> InputSpec {
643 return InputSpec{
644 spec.binding.value,
645 concrete.origin,
646 concrete.description,
647 concrete.subSpec,
648 spec.lifetime};
649 },
650 [&spec](ConcreteDataTypeMatcher const& dataType) -> InputSpec {
651 auto&& matcher = DataSpecUtils::dataDescriptorMatcherFrom(dataType);
652 return InputSpec{
653 spec.binding.value,
654 std::move(matcher),
655 spec.lifetime};
656 }},
657 spec.matcher);
658}
659
661{
662 std::regex word_regex("(\\w+)");
663 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
664 if (std::distance(words, std::sregex_iterator()) != 4) {
665 throw runtime_error_f("Malformed input spec metadata: %s", s.c_str());
666 }
667 std::vector<std::string> data;
668 for (auto i = words; i != std::sregex_iterator(); ++i) {
669 data.emplace_back(i->str());
670 }
671 char origin[4];
672 char description[16];
673 std::memcpy(&origin, data[1].c_str(), 4);
674 std::memcpy(&description, data[2].c_str(), 16);
675 auto version = static_cast<o2::header::DataHeader::SubSpecificationType>(std::atoi(data[3].c_str()));
676 return InputSpec{data[0], header::DataOrigin{origin}, header::DataDescription{description}, version, Lifetime::Timeframe};
677}
678
679std::optional<header::DataOrigin> DataSpecUtils::getOptionalOrigin(InputSpec const& spec)
680{
681 // FIXME: try to address at least a few cases.
682 return std::visit(overloaded{
683 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataOrigin> {
684 return std::make_optional(concrete.origin);
685 },
686 [](DataDescriptorMatcher const& matcher) -> std::optional<header::DataOrigin> {
687 auto state = extractMatcherInfo(matcher);
688 if (state.hasUniqueOrigin) {
689 return std::make_optional(state.origin);
690 } else if (state.hasError) {
691 throw runtime_error("Could not extract origin from query");
692 }
693 return {};
694 }},
695 spec.matcher);
696}
697
698std::optional<header::DataDescription> DataSpecUtils::getOptionalDescription(InputSpec const& spec)
699{
700 // FIXME: try to address at least a few cases.
701 return std::visit(overloaded{
702 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataDescription> {
703 return std::make_optional(concrete.description);
704 },
705 [](DataDescriptorMatcher const& matcher) -> std::optional<header::DataDescription> {
706 auto state = extractMatcherInfo(matcher);
707 if (state.hasUniqueDescription) {
708 return std::make_optional(state.description);
709 } else if (state.hasError) {
710 throw runtime_error("Could not extract description from query");
711 }
712 return {};
713 }},
714 spec.matcher);
715}
716
717std::optional<header::DataHeader::SubSpecificationType> DataSpecUtils::getOptionalSubSpec(OutputSpec const& spec)
718{
719 return std::visit(overloaded{
720 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
721 return std::make_optional(concrete.subSpec);
722 },
723 [](ConcreteDataTypeMatcher const&) -> std::optional<header::DataHeader::SubSpecificationType> {
724 return {};
725 }},
726 spec.matcher);
727}
728
729std::optional<header::DataHeader::SubSpecificationType> DataSpecUtils::getOptionalSubSpec(InputSpec const& spec)
730{
731 // FIXME: try to address at least a few cases.
732 return std::visit(overloaded{
733 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
734 return std::make_optional(concrete.subSpec);
735 },
736 [](DataDescriptorMatcher const& matcher) -> std::optional<header::DataHeader::SubSpecificationType> {
737 auto state = extractMatcherInfo(matcher);
738 if (state.hasUniqueSubSpec) {
739 return std::make_optional(state.subSpec);
740 } else if (state.hasError) {
741 throw runtime_error("Could not extract subSpec from query");
742 }
743 return {};
744 }},
745 spec.matcher);
746}
747
749{
750 return std::visit(
752 [&left](ConcreteDataMatcher const& rightMatcher) {
753 return match(left, rightMatcher);
754 },
755 [&left](DataDescriptorMatcher const& rightMatcher) {
756 auto rightInfo = extractMatcherInfo(rightMatcher);
757 return std::visit(
759 [&rightInfo](ConcreteDataMatcher const& leftMatcher) {
760 return rightInfo.hasUniqueOrigin && rightInfo.origin == leftMatcher.origin &&
761 rightInfo.hasUniqueDescription && rightInfo.description == leftMatcher.description &&
762 rightInfo.hasUniqueSubSpec && rightInfo.subSpec == leftMatcher.subSpec;
763 },
764 [&rightInfo](DataDescriptorMatcher const& leftMatcher) {
765 auto leftInfo = extractMatcherInfo(leftMatcher);
766 return (!leftInfo.hasOrigin || (rightInfo.hasOrigin && leftInfo.origin == rightInfo.origin)) &&
767 (!leftInfo.hasDescription || (rightInfo.hasDescription && leftInfo.description == rightInfo.description)) &&
768 (!leftInfo.hasSubSpec || (rightInfo.hasSubSpec && leftInfo.subSpec == rightInfo.subSpec));
769 }},
770 left.matcher);
771 }},
772 right.matcher);
773}
774
775void DataSpecUtils::updateInputList(std::vector<InputSpec>& list, InputSpec&& input)
776{
777 auto locate = std::find(list.begin(), list.end(), input);
778 if (locate != list.end()) {
779 // amend entry
780 auto& entryMetadata = locate->metadata;
781 entryMetadata.insert(entryMetadata.end(), input.metadata.begin(), input.metadata.end());
782 std::sort(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name < b.name; });
783 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name == b.name; });
784 entryMetadata.erase(new_end, entryMetadata.end());
785 } else {
786 // add entry
787 list.emplace_back(std::move(input));
788 }
789}
790
791void DataSpecUtils::updateOutputList(std::vector<OutputSpec>& list, OutputSpec&& spec)
792{
793 auto locate = std::find(list.begin(), list.end(), spec);
794 if (locate != list.end()) {
795 // amend entry
796 auto& entryMetadata = locate->metadata;
797 entryMetadata.insert(entryMetadata.end(), spec.metadata.begin(), spec.metadata.end());
798 std::sort(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name < b.name; });
799 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name == b.name; });
800 entryMetadata.erase(new_end, entryMetadata.end());
801 } else {
802 // add entry
803 list.emplace_back(std::move(spec));
804 }
805}
806
807} // namespace o2::framework
benchmark::State & state
int32_t i
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint32_t version
Definition RawData.h:8
Something which can be matched against a header::DataDescription.
Something which can be matched against a header::DataOrigin.
Matcher on actual time, as reported in the DataProcessingHeader.
Something which can be matched against a header::SubSpecificationType.
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint buffer
Definition glcorearb.h:655
GLsizeiptr size
Definition glcorearb.h:659
GLdouble GLdouble GLdouble GLdouble top
Definition glcorearb.h:4077
GLdouble GLdouble right
Definition glcorearb.h:4077
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum target
Definition glcorearb.h:1641
GLint left
Definition glcorearb.h:1979
GLboolean * data
Definition glcorearb.h:298
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
constexpr o2::header::DataDescription gDataDescriptionInvalid
Definition DataHeader.h:596
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:561
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
RuntimeErrorRef runtime_error(const char *)
MatcherInfo extractMatcherInfo(DataDescriptorMatcher const &top)
RuntimeErrorRef runtime_error_f(const char *,...)
constexpr auto join(Ts const &... t)
Definition ASoA.h:3294
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
Definition list.h:40
header::DataHeader::SubSpecificationType subSpec
static std::optional< ConcreteDataMatcher > asOptionalConcreteDataMatcher(OutputSpec const &spec)
static bool partialMatch(InputSpec const &spec, o2::header::DataOrigin const &origin)
static InputSpec fromMetadataString(std::string s)
Create an InputSpec from metadata string.
static std::string describe(InputSpec const &spec)
static void updateOutputList(std::vector< OutputSpec > &list, OutputSpec &&input)
Updates list of OutputSpecs by merging metadata (or adding output).
static ConcreteDataTypeMatcher asConcreteDataTypeMatcher(OutputSpec const &spec)
static bool validate(InputSpec const &input)
static ConcreteDataMatcher asConcreteDataMatcher(InputSpec const &input)
static std::optional< header::DataHeader::SubSpecificationType > getOptionalSubSpec(OutputSpec const &spec)
Get the subspec, if available.
static InputSpec matchingInput(OutputSpec const &spec)
static data_matcher::DataDescriptorMatcher dataDescriptorMatcherFrom(ConcreteDataMatcher const &concrete)
Build a DataDescriptMatcher which does not care about the subSpec.
static std::optional< framework::ConcreteDataMatcher > optionalConcreteDataMatcherFrom(data_matcher::DataDescriptorMatcher const &matcher)
static std::string restEndpoint(InputSpec const &spec)
static std::optional< header::DataDescription > getOptionalDescription(InputSpec const &spec)
Get the description, if available.
static std::optional< header::DataOrigin > getOptionalOrigin(InputSpec const &spec)
Get the origin, if available.
static void updateMatchingSubspec(InputSpec &in, header::DataHeader::SubSpecificationType subSpec)
static bool includes(const InputSpec &left, const InputSpec &right)
Checks if left includes right (or is equal to)
static header::DataOrigin asConcreteOrigin(InputSpec const &spec)
static void updateInputList(std::vector< InputSpec > &list, InputSpec &&input)
Updates list of InputSpecs by merging metadata.
static header::DataDescription asConcreteDataDescription(InputSpec const &spec)
static std::string label(InputSpec const &spec)
static OutputSpec asOutputSpec(InputSpec const &spec)
static bool match(InputSpec const &spec, ConcreteDataMatcher const &target)
enum Lifetime lifetime
Definition InputSpec.h:73
std::string binding
A mnemonic name for the input spec.
Definition InputSpec.h:66
std::variant< ConcreteDataMatcher, data_matcher::DataDescriptorMatcher > matcher
The actual matcher for the input spec.
Definition InputSpec.h:70
std::variant< ConcreteDataMatcher, ConcreteDataTypeMatcher > matcher
Definition OutputSpec.h:36
A typesafe reference to an element of the context.
static void walk(DataDescriptorMatcher const &top, EDGEWALKER edgeWalker, LEAFWALKER leafWalker)
From https://en.cppreference.com/w/cpp/utility/variant/visit.
uint32_t SubSpecificationType
Definition DataHeader.h:620
std::enable_if_t< std::is_same< T, std::string >::value==true, T > as() const
get the descriptor as std::string
Definition DataHeader.h:301