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{
220 target.origin,
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
unsigned int uint32_t
std::vector< std::string > header
int32_t i
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
SurfaceTrackState state
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 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:600
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:564
constexpr framework::ConcreteDataMatcher matcher()
Definition ASoA.h:388
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
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:3506
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
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.
T as() const
get the descriptor as std::string
Definition DataHeader.h:304