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
52
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
93{
94 return join(matcher, "/");
95}
96
97template <HasMatcher T>
98size_t DataSpecUtils::describe(char* buffer, size_t size, T const& spec)
99{
100 auto result = std::visit(overloaded{
101 [buffer, size](ConcreteDataMatcher const& concrete) -> fmt::format_to_n_result<char*> {
102 return fmt::format_to_n(buffer, size - 1, "{:.4}/{:.16}/{}", concrete.origin.str, concrete.description.str, concrete.subSpec);
103 },
104 [buffer, size](ConcreteDataTypeMatcher const& concrete) -> fmt::format_to_n_result<char*> {
105 return fmt::format_to_n(buffer, size - 1, "<matcher query: {}/{}>", concrete.origin, concrete.description);
106 },
107 [buffer, size](DataDescriptorMatcher const& matcher) -> fmt::format_to_n_result<char*> {
108 std::ostringstream ss;
109 ss << "<matcher query: " << matcher << ">";
110 return fmt::format_to_n(buffer, size - 1, "{}", ss.str());
111 },
112 [](...) -> fmt::format_to_n_result<char*> { throw std::runtime_error("Unsupported Input / Output Spec"); }},
113 spec.matcher);
114 *result.out = '\0';
115 return result.out - buffer;
116}
117
118template size_t DataSpecUtils::describe(char* buffer, size_t size, InputSpec const& spec);
119template size_t DataSpecUtils::describe(char* buffer, size_t size, OutputSpec const& spec);
120
121std::string DataSpecUtils::label(InputSpec const& spec)
122{
123 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
124 return join(*concrete, "_");
125 } else if (auto matcher = std::get_if<DataDescriptorMatcher>(&spec.matcher)) {
126 std::ostringstream ss;
127 ss << *matcher;
128 std::hash<std::string> hash_fn;
129 auto s = ss.str();
130 auto result = std::to_string(hash_fn(s));
131
132 return result;
133 }
134 throw runtime_error("Unsupported InputSpec");
135}
136
137std::string DataSpecUtils::label(OutputSpec const& spec)
138{
139 // FIXME: unite with the InputSpec one...
140 return std::visit(overloaded{[](auto const& matcher) {
141 return join(matcher, "_");
142 }},
143 spec.matcher);
144}
145
147{
148 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
149 return std::string("/") + join(*concrete, "/");
150 } else {
151 throw runtime_error("Unsupported InputSpec kind");
152 }
153}
154
156{
157 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
158 concrete->subSpec = subSpec;
159 } else {
160 // FIXME: this will only work for the cases in which we do have a dataType defined.
161 auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec);
162 spec.matcher = ConcreteDataMatcher(dataType.origin, dataType.description, subSpec);
163 }
164}
165
167{
168 std::visit(overloaded{
169 [&subSpec](ConcreteDataMatcher& concrete) {
170 concrete.subSpec = subSpec;
171 },
172 [&spec, &subSpec](ConcreteDataTypeMatcher& dataType) {
174 dataType.origin,
175 dataType.description,
176 subSpec};
177 },
178 },
179 spec.matcher);
180}
181
183{
184 using namespace header;
185 if (spec.binding.empty()) {
186 return false;
187 }
188 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
189 return (concrete->description != DataDescription("")) &&
190 (concrete->description != header::gDataDescriptionInvalid) &&
191 (concrete->origin != DataOrigin("")) &&
192 (concrete->origin != header::gDataOriginInvalid);
193 }
194 return true;
195}
196
198{
199 using namespace header;
200 auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec);
201 return (dataType.description != DataDescription("")) &&
202 (dataType.description != header::gDataDescriptionInvalid) &&
203 (dataType.origin != DataOrigin("")) &&
204 (dataType.origin != header::gDataOriginInvalid);
205}
206
208{
209 return std::visit(overloaded{
210 [](ConcreteDataMatcher const& matcher) {
211 // We return false because the matcher is more
212 // qualified (has subSpec) than the target.
213 return false;
214 },
215 [&target](DataDescriptorMatcher const& matcher) {
216 // FIXME: to do it properly we should actually make sure that the
217 // matcher is invariant for changes of SubSpecification. Maybe it's
218 // enough to check that none of the nodes actually match on SubSpec.
219 ConcreteDataMatcher concreteExample{
221 target.description,
222 static_cast<header::DataHeader::SubSpecificationType>(0xffffffff)};
224 return matcher.match(concreteExample, context);
225 }},
226 spec.matcher);
227}
228
230{
231 if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) {
232 return *concrete == target;
233 } else if (auto matcher = std::get_if<DataDescriptorMatcher>(&spec.matcher)) {
235 return matcher->match(target, context);
236 } else {
237 throw runtime_error("Unsupported InputSpec");
238 }
239}
240
242{
243 return std::visit(overloaded{
244 [&target](ConcreteDataMatcher const& concrete) {
245 return concrete == target;
246 },
247 [&target](ConcreteDataTypeMatcher const& concrete) {
248 return concrete.origin == target.origin &&
249 concrete.description == target.description;
250 }},
251 spec.matcher);
252}
253
255{
256 if (auto leftConcrete = std::get_if<ConcreteDataMatcher>(&left.matcher)) {
257 return match(right, *leftConcrete);
258 } else if (auto rightConcrete = std::get_if<ConcreteDataMatcher>(&right.matcher)) {
259 return match(left, *rightConcrete);
260 } else {
261 // both sides are ConcreteDataTypeMatcher without subspecification, we simply specify 0
262 // this is ignored in the mathing since also left hand object is ConcreteDataTypeMatcher
264 return match(left, dataType.origin, dataType.description, 0);
265 }
266}
267
269{
270 return std::visit([&input](auto const& concrete) -> bool {
271 return DataSpecUtils::match(input, concrete);
272 },
273 output.matcher);
274}
275
277{
279 return dataType.origin == origin;
280}
281
286
288{
289 try {
291 } catch (...) {
292 return false;
293 }
294}
295
297{
298 try {
300 } catch (...) {
301 return false;
302 }
303}
304
306 header::DataOrigin origin = header::gDataOriginInvalid; // Whether or not we found an origins (should be a bad query!)
307 header::DataDescription description = header::gDataDescriptionInvalid; // Whether or not we found a description
308 header::DataHeader::SubSpecificationType subSpec = 0; // Whether or not we found a description
309 bool hasOrigin = false;
310 bool hasDescription = false;
311 bool hasSubSpec = false;
312 bool hasUniqueOrigin = false; // Whether the matcher involves a unique origin
313 bool hasUniqueDescription = false; // Whether the matcher involves a unique origin
314 bool hasUniqueSubSpec = false;
315 bool hasError = false;
316};
317
319{
320 using namespace data_matcher;
321 using ops = DataDescriptorMatcher::Op;
322
324 auto nodeWalker = overloaded{
325 [&state](EdgeActions::EnterNode action) {
326 if (state.hasError) {
327 return VisitNone;
328 }
329 // For now we do not support extracting a type from things
330 // which have an OR, so we reset all the uniqueness attributes.
331 if (action.node->getOp() == ops::Or || action.node->getOp() == ops::Xor) {
332 state.hasError = true;
333 return VisitNone;
334 }
335 if (action.node->getOp() == ops::Just ||
336 action.node->getOp() == ops::Not) {
337 return VisitLeft;
338 }
339 return VisitBoth;
340 },
341 [](auto) { return VisitNone; }};
342
343 auto leafWalker = overloaded{
344 [&state](OriginValueMatcher const& valueMatcher) {
345 // FIXME: If we found already more than one data origin, it means
346 // we are ANDing two incompatible origins. Until we support OR,
347 // this is an error.
348 // In case we find a ContextRef, it means we have
349 // a wildcard, so there is not a unique origin.
350 if (state.hasOrigin) {
351 state.hasError = false;
352 return;
353 }
354 state.hasOrigin = true;
355
356 valueMatcher.visit(overloaded{
357 [&state](std::string const& s) {
358 strncpy(state.origin.str, s.data(), 4);
359 state.hasUniqueOrigin = true;
360 },
361 [&state](auto) { state.hasUniqueOrigin = false; }});
362 },
363 [&state](DescriptionValueMatcher const& valueMatcher) {
364 if (state.hasDescription) {
365 state.hasError = true;
366 return;
367 }
368 state.hasDescription = true;
369 valueMatcher.visit(overloaded{
370 [&state](std::string const& s) {
371 strncpy(state.description.str, s.data(), 16);
372 state.hasUniqueDescription = true;
373 },
374 [&state](auto) { state.hasUniqueDescription = false; }});
375 },
376 [&state](SubSpecificationTypeValueMatcher const& valueMatcher) {
377 if (state.hasSubSpec) {
378 state.hasError = true;
379 return;
380 }
381 state.hasSubSpec = true;
382 valueMatcher.visit(overloaded{
383 [&state](uint32_t const& data) {
384 state.subSpec = data;
385 state.hasUniqueSubSpec = true;
386 },
387 [&state](auto) { state.hasUniqueSubSpec = false; }});
388 },
389 [](auto t) {}};
390 DataMatcherWalker::walk(top, nodeWalker, leafWalker);
391 return state;
392}
393
395{
396 return std::visit(overloaded{[](ConcreteDataMatcher const& concrete) {
397 return concrete;
398 },
399 [&binding = spec.binding](DataDescriptorMatcher const& matcher) {
400 auto info = extractMatcherInfo(matcher);
401 if (info.hasOrigin && info.hasUniqueOrigin &&
402 info.hasDescription && info.hasDescription &&
403 info.hasSubSpec && info.hasUniqueSubSpec) {
404 return ConcreteDataMatcher{info.origin, info.description, info.subSpec};
405 }
406 throw std::runtime_error("Cannot convert " + binding + " to ConcreteDataMatcher");
407 }},
408 spec.matcher);
409}
410
412{
413 return std::get<ConcreteDataMatcher>(spec.matcher);
414}
415
416std::optional<ConcreteDataMatcher> DataSpecUtils::asOptionalConcreteDataMatcher(OutputSpec const& spec)
417{
418 return std::visit(overloaded{
419 [](ConcreteDataMatcher const& concrete) {
420 return std::optional<ConcreteDataMatcher>{concrete};
421 },
422 [](DataDescriptorMatcher const& matcher) {
424 },
425 [](auto const&) { return std::optional<ConcreteDataMatcher>{std::nullopt}; }},
426 spec.matcher);
427}
428
430{
431 return std::visit([](auto const& concrete) {
432 return ConcreteDataTypeMatcher{concrete.origin, concrete.description};
433 },
434 spec.matcher);
435}
436
438{
439 return std::visit(overloaded{
440 [](auto const& concrete) {
441 return ConcreteDataTypeMatcher{concrete.origin, concrete.description};
442 },
443 [](DataDescriptorMatcher const& matcher) {
444 auto state = extractMatcherInfo(matcher);
445 if (state.hasUniqueOrigin && state.hasUniqueDescription) {
446 return ConcreteDataTypeMatcher{state.origin, state.description};
447 }
448 throw runtime_error("Could not extract data type from query");
449 }},
450 spec.matcher);
451}
452
454{
455 return std::visit(overloaded{
456 [](auto const& concrete) {
457 return concrete.origin;
458 },
459 [](DataDescriptorMatcher const& matcher) {
460 auto state = extractMatcherInfo(matcher);
461 if (state.hasUniqueOrigin) {
462 return state.origin;
463 }
464 throw runtime_error("Could not extract data type from query");
465 }},
466 spec.matcher);
467}
468
470{
471 return std::visit(overloaded{
472 [](auto const& concrete) {
473 return concrete.description;
474 },
475 [](DataDescriptorMatcher const& matcher) {
476 auto state = extractMatcherInfo(matcher);
477 if (state.hasUniqueDescription) {
478 return state.description;
479 }
480 throw runtime_error("Could not extract data type from query");
481 }},
482 spec.matcher);
483}
484
486{
487 return std::visit(overloaded{
488 [&spec](ConcreteDataMatcher const& concrete) {
489 return OutputSpec{{spec.binding}, concrete, spec.lifetime};
490 },
491 [&spec](DataDescriptorMatcher const& matcher) {
492 auto state = extractMatcherInfo(matcher);
493 if (state.hasUniqueOrigin && state.hasUniqueDescription && state.hasUniqueSubSpec) {
494 return OutputSpec{{spec.binding}, ConcreteDataMatcher{state.origin, state.description, state.subSpec}, spec.lifetime};
495 } else if (state.hasUniqueOrigin && state.hasUniqueDescription) {
496 return OutputSpec{{spec.binding}, ConcreteDataTypeMatcher{state.origin, state.description}, spec.lifetime};
497 }
498
499 throw runtime_error_f("Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query %s", describe(spec).c_str());
500 }},
501 spec.matcher);
502}
503
505{
506 DataDescriptorMatcher matchEverything{
507 DataDescriptorMatcher::Op::And,
508 OriginValueMatcher{concrete.origin.as<std::string>()},
509 std::make_unique<DataDescriptorMatcher>(
510 DataDescriptorMatcher::Op::And,
511 DescriptionValueMatcher{concrete.description.as<std::string>()},
512 std::make_unique<DataDescriptorMatcher>(
513 DataDescriptorMatcher::Op::And,
515 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
517 return matchEverything;
518}
519
521{
522 auto timeDescriptionMatcher = std::make_unique<DataDescriptorMatcher>(
523 DataDescriptorMatcher::Op::And,
524 DescriptionValueMatcher{dataType.description.as<std::string>()},
525 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
528 DataDescriptorMatcher::Op::And,
529 OriginValueMatcher{dataType.origin.as<std::string>()},
530 std::move(timeDescriptionMatcher));
531}
532
534{
535 char buf[5] = {0, 0, 0, 0, 0};
536 strncpy(buf, origin.str, 4);
537 DataDescriptorMatcher matchOnlyOrigin{
538 DataDescriptorMatcher::Op::And,
540 std::make_unique<DataDescriptorMatcher>(
541 DataDescriptorMatcher::Op::And,
543 std::make_unique<DataDescriptorMatcher>(
544 DataDescriptorMatcher::Op::And,
546 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
548 return matchOnlyOrigin;
549}
550
552{
553 char buf[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
554 strncpy(buf, description.str, 16);
555 DataDescriptorMatcher matchOnlyOrigin{
556 DataDescriptorMatcher::Op::And,
558 std::make_unique<DataDescriptorMatcher>(
559 DataDescriptorMatcher::Op::And,
561 std::make_unique<DataDescriptorMatcher>(
562 DataDescriptorMatcher::Op::And,
564 std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just,
566 return matchOnlyOrigin;
567}
568
569std::optional<framework::ConcreteDataMatcher> DataSpecUtils::optionalConcreteDataMatcherFrom(data_matcher::DataDescriptorMatcher const& matcher)
570{
571 using namespace data_matcher;
572 using ops = DataDescriptorMatcher::Op;
573
575 auto nodeWalker = overloaded{
576 [&state](EdgeActions::EnterNode action) {
577 if (state.hasError) {
578 return VisitNone;
579 }
580 // a ConcreteDataMatcher requires either 'and' or 'just'
581 // operations and we return the corresponding action for these
582 if (action.node->getOp() == ops::Just) {
583 return VisitLeft;
584 } else if (action.node->getOp() == ops::And) {
585 return VisitBoth;
586 }
587 // simply use the error state to indicate that the operation does not match the
588 // requirement for fully qualified ConcreteDataMatcher
589 state.hasError = true;
590 return VisitNone;
591 },
592 [](auto) { return VisitNone; }};
593
594 auto leafWalker = overloaded{
595 [&state](OriginValueMatcher const& valueMatcher) {
596 // if this is not the first OriginValueMatcher, the value can not be unique
597 if (state.hasOrigin) {
598 state.hasUniqueOrigin = false;
599 return;
600 }
601 state.hasOrigin = true;
602
603 valueMatcher.visit(overloaded{
604 [&state](std::string const& s) {
605 strncpy(state.origin.str, s.data(), 4);
606 state.hasUniqueOrigin = true;
607 },
608 [&state](auto) { state.hasUniqueOrigin = false; }});
609 },
610 [&state](DescriptionValueMatcher const& valueMatcher) {
611 if (state.hasDescription) {
612 state.hasUniqueDescription = false;
613 return;
614 }
615 state.hasDescription = true;
616 valueMatcher.visit(overloaded{
617 [&state](std::string const& s) {
618 strncpy(state.description.str, s.data(), 16);
619 state.hasUniqueDescription = true;
620 },
621 [&state](auto) { state.hasUniqueDescription = false; }});
622 },
623 [&state](SubSpecificationTypeValueMatcher const& valueMatcher) {
624 if (state.hasSubSpec) {
625 state.hasUniqueSubSpec = false;
626 return;
627 }
628 state.hasSubSpec = true;
629 valueMatcher.visit(overloaded{
630 [&state](uint32_t const& data) {
631 state.subSpec = data;
632 state.hasUniqueSubSpec = true;
633 },
634 [&state](auto) { state.hasUniqueSubSpec = false; }});
635 },
636 [](auto t) {}};
637 DataMatcherWalker::walk(matcher, nodeWalker, leafWalker);
638 if (state.hasError == false && state.hasUniqueOrigin && state.hasUniqueDescription && state.hasUniqueSubSpec) {
639 return std::make_optional(ConcreteDataMatcher{state.origin, state.description, state.subSpec});
640 }
641 return {};
642}
643
645{
646 return std::visit(overloaded{
647 [&spec](ConcreteDataMatcher const& concrete) -> InputSpec {
648 return InputSpec{
649 spec.binding.value,
650 concrete.origin,
651 concrete.description,
652 concrete.subSpec,
653 spec.lifetime};
654 },
655 [&spec](ConcreteDataTypeMatcher const& dataType) -> InputSpec {
656 auto&& matcher = DataSpecUtils::dataDescriptorMatcherFrom(dataType);
657 return InputSpec{
658 spec.binding.value,
659 std::move(matcher),
660 spec.lifetime};
661 }},
662 spec.matcher);
663}
664
666{
667 std::regex word_regex("(\\w+)");
668 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
669 if (std::distance(words, std::sregex_iterator()) != 4) {
670 throw runtime_error_f("Malformed input spec metadata: %s", s.c_str());
671 }
672 std::array<std::string, 4> data;
673 auto pos = 0;
674 for (auto i = words; i != std::sregex_iterator(); ++i) {
675 data[pos] = i->str();
676 ++pos;
677 }
678 char origin[4];
679 char description[16];
680 std::memcpy(&origin, data[1].c_str(), 4);
681 std::memcpy(&description, data[2].c_str(), 16);
682 auto version = static_cast<o2::header::DataHeader::SubSpecificationType>(std::atoi(data[3].c_str()));
683 return {data[0], header::DataOrigin{origin}, header::DataDescription{description}, version, Lifetime::Timeframe};
684}
685
687{
688 std::regex word_regex("(\\w+)");
689 auto words = std::sregex_iterator(s.begin(), s.end(), word_regex);
690 if (std::distance(words, std::sregex_iterator()) != 3) {
691 throw runtime_error_f("Malformed serialized matcher: %s", s.c_str());
692 }
693 std::array<std::string, 3> data;
694 auto pos = 0;
695 for (auto i = words; i != std::sregex_iterator(); ++i) {
696 data[pos] = i->str();
697 ++pos;
698 }
699 char origin[4];
700 char description[16];
701 std::memcpy(&origin, data[0].c_str(), 4);
702 std::memcpy(&description, data[1].c_str(), 16);
703 auto version = static_cast<o2::header::DataHeader::SubSpecificationType>(std::atoi(data[2].c_str()));
705}
706
707std::optional<header::DataOrigin> DataSpecUtils::getOptionalOrigin(InputSpec const& spec)
708{
709 // FIXME: try to address at least a few cases.
710 return std::visit(overloaded{
711 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataOrigin> {
712 return std::make_optional(concrete.origin);
713 },
714 [](DataDescriptorMatcher const& matcher) -> std::optional<header::DataOrigin> {
715 auto state = extractMatcherInfo(matcher);
716 if (state.hasUniqueOrigin) {
717 return std::make_optional(state.origin);
718 } else if (state.hasError) {
719 throw runtime_error("Could not extract origin from query");
720 }
721 return {};
722 }},
723 spec.matcher);
724}
725
726std::optional<header::DataDescription> DataSpecUtils::getOptionalDescription(InputSpec const& spec)
727{
728 // FIXME: try to address at least a few cases.
729 return std::visit(overloaded{
730 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataDescription> {
731 return std::make_optional(concrete.description);
732 },
733 [](DataDescriptorMatcher const& matcher) -> std::optional<header::DataDescription> {
734 auto state = extractMatcherInfo(matcher);
735 if (state.hasUniqueDescription) {
736 return std::make_optional(state.description);
737 } else if (state.hasError) {
738 throw runtime_error("Could not extract description from query");
739 }
740 return {};
741 }},
742 spec.matcher);
743}
744
745std::optional<header::DataHeader::SubSpecificationType> DataSpecUtils::getOptionalSubSpec(OutputSpec const& spec)
746{
747 return std::visit(overloaded{
748 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
749 return std::make_optional(concrete.subSpec);
750 },
751 [](ConcreteDataTypeMatcher const&) -> std::optional<header::DataHeader::SubSpecificationType> {
752 return {};
753 }},
754 spec.matcher);
755}
756
757std::optional<header::DataHeader::SubSpecificationType> DataSpecUtils::getOptionalSubSpec(InputSpec const& spec)
758{
759 // FIXME: try to address at least a few cases.
760 return std::visit(overloaded{
761 [](ConcreteDataMatcher const& concrete) -> std::optional<header::DataHeader::SubSpecificationType> {
762 return std::make_optional(concrete.subSpec);
763 },
764 [](DataDescriptorMatcher const& matcher) -> std::optional<header::DataHeader::SubSpecificationType> {
765 auto state = extractMatcherInfo(matcher);
766 if (state.hasUniqueSubSpec) {
767 return std::make_optional(state.subSpec);
768 } else if (state.hasError) {
769 throw runtime_error("Could not extract subSpec from query");
770 }
771 return {};
772 }},
773 spec.matcher);
774}
775
777{
778 return std::visit(
780 [&left](ConcreteDataMatcher const& rightMatcher) {
781 return match(left, rightMatcher);
782 },
783 [&left](DataDescriptorMatcher const& rightMatcher) {
784 auto rightInfo = extractMatcherInfo(rightMatcher);
785 return std::visit(
787 [&rightInfo](ConcreteDataMatcher const& leftMatcher) {
788 return rightInfo.hasUniqueOrigin && rightInfo.origin == leftMatcher.origin &&
789 rightInfo.hasUniqueDescription && rightInfo.description == leftMatcher.description &&
790 rightInfo.hasUniqueSubSpec && rightInfo.subSpec == leftMatcher.subSpec;
791 },
792 [&rightInfo](DataDescriptorMatcher const& leftMatcher) {
793 auto leftInfo = extractMatcherInfo(leftMatcher);
794 return (!leftInfo.hasOrigin || (rightInfo.hasOrigin && leftInfo.origin == rightInfo.origin)) &&
795 (!leftInfo.hasDescription || (rightInfo.hasDescription && leftInfo.description == rightInfo.description)) &&
796 (!leftInfo.hasSubSpec || (rightInfo.hasSubSpec && leftInfo.subSpec == rightInfo.subSpec));
797 }},
798 left.matcher);
799 }},
800 right.matcher);
801}
802
803void DataSpecUtils::updateInputList(std::vector<InputSpec>& list, InputSpec&& input)
804{
805 auto locate = std::find(list.begin(), list.end(), input);
806 if (locate != list.end()) {
807 // amend entry
808 auto& entryMetadata = locate->metadata;
809 entryMetadata.insert(entryMetadata.end(), input.metadata.begin(), input.metadata.end());
810 std::sort(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name < b.name; });
811 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name == b.name; });
812 entryMetadata.erase(new_end, entryMetadata.end());
813 } else {
814 // add entry
815 list.emplace_back(std::move(input));
816 }
817}
818
819void DataSpecUtils::updateOutputList(std::vector<OutputSpec>& list, OutputSpec&& spec)
820{
821 auto locate = std::find(list.begin(), list.end(), spec);
822 if (locate != list.end()) {
823 // amend entry
824 auto& entryMetadata = locate->metadata;
825 entryMetadata.insert(entryMetadata.end(), spec.metadata.begin(), spec.metadata.end());
826 std::sort(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name < b.name; });
827 auto new_end = std::unique(entryMetadata.begin(), entryMetadata.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name == b.name; });
828 entryMetadata.erase(new_end, entryMetadata.end());
829 } else {
830 // add entry
831 list.emplace_back(std::move(spec));
832 }
833}
834
835} // namespace o2::framework
header::DataOrigin origin
header::DataDescription description
std::string binding
benchmark::State & state
int32_t i
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint16_t pos
Definition RawData.h:3
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:597
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:561
constexpr framework::ConcreteDataMatcher matcher()
Definition ASoA.h:380
Defining PrimaryVertex explicitly as messageable.
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:3489
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 ConcreteDataMatcher fromString(std::string s)
Create a concrete data matcher from serialized string.
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:621
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