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