Project
Loading...
Searching...
No Matches
DataDescriptorMatcher.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.
11
18#include "Headers/DataHeader.h"
19#include "Headers/Stack.h"
20#include <array>
21#include <iostream>
22#include <memory_resource>
23
25{
26
28{
29 // First we check if there is any pending update
30 for (size_t i = 0; i < mPerformedUpdates; ++i) {
31 if (mUpdates[i].position == pos) {
32 return mUpdates[i].newValue;
33 }
34 }
35 // Otherwise we return the element.
36 return mElements.at(pos).value;
37}
38
39void VariableContext::publish(void (*callback)(VariableContext const&, TimesliceSlot slot, void*), void* context, TimesliceSlot slot)
40{
41 bool anyPublish = false;
42 for (size_t i = 0; i < MAX_MATCHING_VARIABLE; i++) {
43 auto& element = mElements[i];
44
45 if (element.commitVersion == element.publishVersion) {
46 continue;
47 }
48 element.publishVersion = element.commitVersion;
49 anyPublish = true;
50 }
51 if (anyPublish) {
52 callback(*this, slot, context);
53 }
54}
55
57{
58 for (size_t i = 0; i < mPerformedUpdates; ++i) {
59 auto& element = mElements[mUpdates[i].position];
60 element.value = mUpdates[i].newValue;
61 element.commitVersion++;
62 }
63 mPerformedUpdates = 0;
64}
65
67{
68 mPerformedUpdates = 0;
69 for (auto& element : mElements) {
70 element.value = None{};
71 }
72}
73
75{
76 if (auto ref = std::get_if<ContextRef>(&mValue)) {
77 auto& variable = context.get(ref->index);
78 if (auto value = std::get_if<std::string>(&variable)) {
79 return strncmp(header.dataOrigin.str, value->c_str(), header::DataOrigin::size) == 0;
80 }
81 auto maxSize = strnlen(header.dataOrigin.str, header::DataOrigin::size);
82 context.put({ref->index, std::string(header.dataOrigin.str, maxSize)});
83 return true;
84 } else if (auto s = std::get_if<std::string>(&mValue)) {
85 return strncmp(header.dataOrigin.str, s->c_str(), header::DataOrigin::size) == 0;
86 }
87 throw runtime_error("Mismatching type for variable");
88}
89
91{
92 if (auto ref = std::get_if<ContextRef>(&mValue)) {
93 auto& variable = context.get(ref->index);
94 if (auto value = std::get_if<std::string>(&variable)) {
95 return strncmp(header.dataDescription.str, value->c_str(), header::DataDescription::size) == 0;
96 }
98 context.put({ref->index, std::string(header.dataDescription.str, maxSize)});
99 return true;
100 } else if (auto s = std::get_if<std::string>(&this->mValue)) {
101 return strncmp(header.dataDescription.str, s->c_str(), header::DataDescription::size) == 0;
102 }
103 throw runtime_error("Mismatching type for variable");
104}
105
107{
108 if (auto ref = std::get_if<ContextRef>(&mValue)) {
109 auto& variable = context.get(ref->index);
110 if (auto value = std::get_if<header::DataHeader::SubSpecificationType>(&variable)) {
111 return header.subSpecification == *value;
112 }
113 context.put({ref->index, header.subSpecification});
114 return true;
115 } else if (auto v = std::get_if<header::DataHeader::SubSpecificationType>(&mValue)) {
116 return header.subSpecification == *v;
117 }
118 throw runtime_error("Mismatching type for variable");
119}
120
125{
126 if (auto ref = std::get_if<ContextRef>(&mValue)) {
127 auto& variable = context.get(ref->index);
128 if (auto value = std::get_if<uint64_t>(&variable)) {
129 return (dph.startTime / mScale) == *value;
130 }
131 context.put({ref->index, dph.startTime / mScale});
132 // We always put in 12 the creation time
133 context.put({CREATIONTIME_POS, dph.creation});
134 // We always put in 13 the runNumber
135 context.put({RUNNUMBER_POS, dh.runNumber});
136 // We always put in 14 the tfCounter
137 context.put({TFCOUNTER_POS, dh.tfCounter});
138 // We always put in 15 the firstTForbit
139 context.put({FIRSTTFORBIT_POS, dh.firstTForbit});
140 return true;
141 } else if (auto v = std::get_if<uint64_t>(&mValue)) {
142 return (dph.startTime / mScale) == *v;
143 }
144 throw runtime_error("Mismatching type for variable");
145}
146
148 : mOp{other.mOp},
149 mLeft{ConstantValueMatcher{false}},
150 mRight{ConstantValueMatcher{false}}
151{
152 if (auto pval0 = std::get_if<OriginValueMatcher>(&other.mLeft)) {
153 mLeft = *pval0;
154 } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&other.mLeft)) {
155 mLeft = *pval1;
156 } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&other.mLeft)) {
157 mLeft = *pval2;
158 } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&other.mLeft)) {
159 mLeft = std::move(std::make_unique<DataDescriptorMatcher>(*pval3->get()));
160 } else if (auto pval4 = std::get_if<ConstantValueMatcher>(&other.mLeft)) {
161 mLeft = *pval4;
162 } else if (auto pval5 = std::get_if<StartTimeValueMatcher>(&other.mLeft)) {
163 mLeft = *pval5;
164 } else {
165 std::cerr << (other.mLeft.index() == std::variant_npos) << std::endl;
167 }
168
169 if (auto pval0 = std::get_if<OriginValueMatcher>(&other.mRight)) {
170 mRight = *pval0;
171 } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&other.mRight)) {
172 mRight = *pval1;
173 } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&other.mRight)) {
174 mRight = *pval2;
175 } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&other.mRight)) {
176 mRight = std::move(std::make_unique<DataDescriptorMatcher>(*pval3->get()));
177 } else if (auto pval4 = std::get_if<ConstantValueMatcher>(&other.mRight)) {
178 mRight = *pval4;
179 } else if (auto pval5 = std::get_if<StartTimeValueMatcher>(&other.mRight)) {
180 mRight = *pval5;
181 } else {
183 }
184}
185
190
193 : mOp{op},
194 mLeft{std::move(lhs)},
195 mRight{std::move(rhs)}
196{
197}
198
202{
204 dh.dataOrigin = matcher.origin;
205 dh.dataDescription = matcher.description;
206 dh.subSpecification = matcher.subSpec;
207 DataProcessingHeader dph{0, 0, 0};
208 alignas(std::max_align_t) std::array<std::byte, sizeof(header::DataHeader) + sizeof(DataProcessingHeader) + alignof(std::max_align_t)> buffer;
209 std::pmr::monotonic_buffer_resource resource{buffer.data(), buffer.size(), std::pmr::null_memory_resource()};
210 header::Stack s{header::Stack::allocator_type{&resource}, dh, dph};
211
212 return this->match(reinterpret_cast<char const*>(s.data()), context);
213}
214
218{
220 dh.dataOrigin = matcher.origin;
221 dh.dataDescription = matcher.description;
222 dh.subSpecification = 0;
223 DataProcessingHeader dph{0, 0, 0};
224 alignas(std::max_align_t) std::array<std::byte, sizeof(header::DataHeader) + sizeof(DataProcessingHeader) + alignof(std::max_align_t)> buffer;
225 std::pmr::monotonic_buffer_resource resource{buffer.data(), buffer.size(), std::pmr::null_memory_resource()};
226 header::Stack s{header::Stack::allocator_type{&resource}, dh, dph};
227
228 return this->match(reinterpret_cast<char const*>(s.data()), context);
229}
230
232{
233 return this->match(reinterpret_cast<char const*>(&header), context);
234}
235
237{
238 return this->match(reinterpret_cast<char const*>(stack.data()), context);
239}
240
241// actual polymorphic matcher which is able to cast the pointer to the correct
242// kind of header.
243bool DataDescriptorMatcher::match(char const* d, VariableContext& context) const
244{
245 bool leftValue = false, rightValue = false;
246
247 // FIXME: Using std::visit is not API compatible due to a new
248 // exception being thrown. This is the ABI compatible version.
249 // Replace with:
250 //
251 // auto eval = [&d](auto&& arg) -> bool {
252 // using T = std::decay_t<decltype(arg)>;
253 // if constexpr (std::is_same_v<T, std::unique_ptr<DataDescriptorMatcher>>) {
254 // return arg->match(d, context);
255 // if constexpr (std::is_same_v<T, ConstantValueMatcher>) {
256 // return arg->match(d);
257 // } else {
258 // return arg.match(d, context);
259 // }
260 // };
261 // switch (mOp) {
262 // case Op::Or:
263 // return std::visit(eval, mLeft) || std::visit(eval, mRight);
264 // case Op::And:
265 // return std::visit(eval, mLeft) && std::visit(eval, mRight);
266 // case Op::Xor:
267 // return std::visit(eval, mLeft) ^ std::visit(eval, mRight);
268 // case Op::Just:
269 // return std::visit(eval, mLeft);
270 // case Op::Not:
271 // return !std::visit(eval, mLeft);
272 // }
273 // When we drop support for macOS 10.13
274 if (auto pval0 = std::get_if<OriginValueMatcher>(&mLeft)) {
275 auto dh = o2::header::get<header::DataHeader*>(d);
276 if (dh == nullptr) {
277 throw runtime_error("Cannot find DataHeader");
278 }
279 leftValue = pval0->match(*dh, context);
280 } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&mLeft)) {
281 auto dh = o2::header::get<header::DataHeader*>(d);
282 if (dh == nullptr) {
283 throw runtime_error("Cannot find DataHeader");
284 }
285 leftValue = pval1->match(*dh, context);
286 } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&mLeft)) {
287 auto dh = o2::header::get<header::DataHeader*>(d);
288 if (dh == nullptr) {
289 throw runtime_error("Cannot find DataHeader");
290 }
291 leftValue = pval2->match(*dh, context);
292 } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&mLeft)) {
293 leftValue = (*pval3)->match(d, context);
294 } else if (auto pval4 = std::get_if<ConstantValueMatcher>(&mLeft)) {
295 leftValue = pval4->match();
296 } else if (auto pval5 = std::get_if<StartTimeValueMatcher>(&mLeft)) {
297 auto dh = o2::header::get<header::DataHeader*>(d);
298 auto dph = o2::header::get<DataProcessingHeader*>(d);
299 if (dph == nullptr) {
300 throw runtime_error("Cannot find DataProcessingHeader");
301 }
302 leftValue = pval5->match(*dh, *dph, context);
303 } else {
304 throw runtime_error("Bad parsing tree");
305 }
306 // Common speedup.
307 if (mOp == Op::And && leftValue == false) {
308 return false;
309 }
310 if (mOp == Op::Or && leftValue == true) {
311 return true;
312 }
313 if (mOp == Op::Just) {
314 return leftValue;
315 }
316 if (mOp == Op::Not) {
317 return !leftValue;
318 }
319
320 if (auto pval0 = std::get_if<OriginValueMatcher>(&mRight)) {
321 auto dh = o2::header::get<header::DataHeader*>(d);
322 rightValue = pval0->match(*dh, context);
323 } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&mRight)) {
324 auto dh = o2::header::get<header::DataHeader*>(d);
325 rightValue = pval1->match(*dh, context);
326 } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&mRight)) {
327 auto dh = o2::header::get<header::DataHeader*>(d);
328 rightValue = pval2->match(*dh, context);
329 } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&mRight)) {
330 rightValue = (*pval3)->match(d, context);
331 } else if (auto pval4 = std::get_if<ConstantValueMatcher>(&mRight)) {
332 rightValue = pval4->match();
333 } else if (auto pval5 = std::get_if<StartTimeValueMatcher>(&mRight)) {
334 auto dh = o2::header::get<header::DataHeader*>(d);
335 auto dph = o2::header::get<DataProcessingHeader*>(d);
336 rightValue = pval5->match(*dh, *dph, context);
337 }
338 // There are cases in which not having a rightValue might be legitimate,
339 // so we do not throw an exception.
340 switch (mOp) {
341 case Op::Or:
342 return leftValue || rightValue;
343 case Op::And:
344 return leftValue && rightValue;
345 case Op::Xor:
346 return leftValue ^ rightValue;
347 case Op::Just:
348 return leftValue;
349 case Op::Not:
350 return !leftValue;
351 }
352 throw runtime_error("Bad parsing tree");
353};
354
356{
357 if (other.mOp != this->mOp) {
358 return false;
359 }
360
361 bool leftValue = false;
362
363 {
364 auto v1 = std::get_if<OriginValueMatcher>(&this->mLeft);
365 auto v2 = std::get_if<OriginValueMatcher>(&other.mLeft);
366 if (v1 && v2 && *v1 == *v2) {
367 leftValue = true;
368 }
369 }
370
371 {
372 auto v1 = std::get_if<DescriptionValueMatcher>(&this->mLeft);
373 auto v2 = std::get_if<DescriptionValueMatcher>(&other.mLeft);
374 if (v1 && v2 && *v1 == *v2) {
375 leftValue = true;
376 }
377 }
378
379 {
380 auto v1 = std::get_if<SubSpecificationTypeValueMatcher>(&this->mLeft);
381 auto v2 = std::get_if<SubSpecificationTypeValueMatcher>(&other.mLeft);
382 if (v1 && v2 && *v1 == *v2) {
383 leftValue = true;
384 }
385 }
386
387 {
388 auto v1 = std::get_if<ConstantValueMatcher>(&this->mLeft);
389 auto v2 = std::get_if<ConstantValueMatcher>(&other.mLeft);
390 if (v1 && v2 && *v1 == *v2) {
391 leftValue = true;
392 }
393 }
394
395 {
396 auto v1 = std::get_if<StartTimeValueMatcher>(&this->mLeft);
397 auto v2 = std::get_if<StartTimeValueMatcher>(&other.mLeft);
398 if (v1 && v2 && *v1 == *v2) {
399 leftValue = true;
400 }
401 }
402
403 {
404 auto v1 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&this->mLeft);
405 auto v2 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&other.mLeft);
406 if (v1 && v2 && v1->get() && v2->get() && (**v1 == **v2)) {
407 leftValue = true;
408 }
409 }
410
411 // Shortcut the fact that the left side is different.
412 if (leftValue == false) {
413 return false;
414 }
415
416 if (mOp == Op::Just) {
417 return leftValue;
418 }
419
420 if (mOp == Op::Not) {
421 return leftValue;
422 }
423
424 {
425 auto v1 = std::get_if<OriginValueMatcher>(&this->mRight);
426 auto v2 = std::get_if<OriginValueMatcher>(&other.mRight);
427 if (v1 && v2 && *v1 == *v2) {
428 return true;
429 }
430 }
431
432 {
433 auto v1 = std::get_if<DescriptionValueMatcher>(&this->mRight);
434 auto v2 = std::get_if<DescriptionValueMatcher>(&other.mRight);
435 if (v1 && v2 && *v1 == *v2) {
436 return true;
437 }
438 }
439
440 {
441 auto v1 = std::get_if<SubSpecificationTypeValueMatcher>(&this->mRight);
442 auto v2 = std::get_if<SubSpecificationTypeValueMatcher>(&other.mRight);
443 if (v1 && v2 && *v1 == *v2) {
444 return true;
445 }
446 }
447
448 {
449 auto v1 = std::get_if<ConstantValueMatcher>(&this->mRight);
450 auto v2 = std::get_if<ConstantValueMatcher>(&other.mRight);
451 if (v1 && v2 && *v1 == *v2) {
452 return true;
453 }
454 }
455
456 {
457 auto v1 = std::get_if<StartTimeValueMatcher>(&this->mRight);
458 auto v2 = std::get_if<StartTimeValueMatcher>(&other.mRight);
459 if (v1 && v2 && *v1 == *v2) {
460 return true;
461 }
462 }
463
464 {
465 auto v1 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&this->mRight);
466 auto v2 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&other.mRight);
467 if (v1 && v2 && v1->get() && v2->get() && (**v1 == **v2)) {
468 return true;
469 }
470 }
471 // We alredy know the left side is true.
472 return false;
473}
474
475std::ostream& operator<<(std::ostream& os, DataDescriptorMatcher const& matcher)
476{
477 auto edgeWalker = overloaded{
478 [&os](EdgeActions::EnterNode action) {
479 os << "(" << action.node->mOp;
480 if (action.node->mOp == DataDescriptorMatcher::Op::Just ||
481 action.node->mOp == DataDescriptorMatcher::Op::Not) {
483 }
485 },
486 [&os](EdgeActions::EnterLeft) { os << " "; },
487 [&os](EdgeActions::ExitLeft) { os << " "; },
488 [&os](EdgeActions::EnterRight) { os << " "; },
489 [&os](EdgeActions::ExitRight) { os << " "; },
490 [&os](EdgeActions::ExitNode) { os << ")"; },
491 [&os](auto) {}};
492 auto leafWalker = overloaded{
493 [&os](OriginValueMatcher const& origin) { os << "origin:" << origin; },
494 [&os](DescriptionValueMatcher const& description) { os << "description:" << description; },
495 [&os](SubSpecificationTypeValueMatcher const& subSpec) { os << "subSpec:" << subSpec; },
496 [&os](StartTimeValueMatcher const& startTime) { os << "startTime:" << startTime; },
497 [&os](ConstantValueMatcher const& constant) {},
498 [&os](auto t) { os << "not implemented " << typeid(decltype(t)).name(); }};
500 edgeWalker,
501 leafWalker);
502
503 return os;
504}
505
506std::ostream& operator<<(std::ostream& os, DataDescriptorMatcher::Op const& op)
507{
508 switch (op) {
510 os << "and";
511 break;
513 os << "or";
514 break;
516 os << "just";
517 break;
519 os << "not";
520 break;
522 os << "xor";
523 break;
524 }
525 return os;
526}
527
528} // namespace o2::framework::data_matcher
header::DataOrigin origin
header::DataDescription description
size_t maxSize
#define O2_BUILTIN_UNREACHABLE
atype::type element
int32_t i
uint32_t op
uint16_t pos
Definition RawData.h:3
uint32_t stack
Definition RawData.h:1
bool match(ConcreteDataMatcher const &matcher, VariableContext &context) const
bool operator==(DataDescriptorMatcher const &other) const
DataDescriptorMatcher & operator=(DataDescriptorMatcher const &other)
DataDescriptorMatcher(DataDescriptorMatcher const &other)
Something which can be matched against a header::DataDescription.
bool match(header::DataHeader const &header, VariableContext &context) const
Something which can be matched against a header::DataOrigin.
bool match(header::DataHeader const &header, VariableContext &context) const
Matcher on actual time, as reported in the DataProcessingHeader.
bool match(header::DataHeader const &dh, DataProcessingHeader const &dph, VariableContext &context) const
Something which can be matched against a header::SubSpecificationType.
bool match(header::DataHeader const &header, VariableContext &context) const
void publish(void(*callback)(VariableContext const &, TimesliceSlot slot, void *context), void *context, TimesliceSlot slot)
ContextElement::Value const & get(size_t pos) const
GLuint buffer
Definition glcorearb.h:655
const GLdouble * v
Definition glcorearb.h:832
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLfloat GLfloat v1
Definition glcorearb.h:812
GLfloat GLfloat GLfloat v2
Definition glcorearb.h:813
std::variant< OriginValueMatcher, DescriptionValueMatcher, SubSpecificationTypeValueMatcher, std::unique_ptr< DataDescriptorMatcher >, ConstantValueMatcher, StartTimeValueMatcher > Node
std::ostream & operator<<(std::ostream &os, DataDescriptorMatcher const &matcher)
@ CREATIONTIME_POS
The DataHeader::runNumber associated to the timeslice.
@ FIRSTTFORBIT_POS
The DataHeader::tfCounter associated to the timeslice.
@ TFCOUNTER_POS
The DataProcessingHeader::startTime associated to the timeslice.
@ RUNNUMBER_POS
The DataHeader::firstTForbit associated to the timeslice.
RuntimeErrorRef runtime_error(const char *)
header::DataHeader::SubSpecificationType subSpec
std::variant< uint32_t, uint64_t, std::string, None > Value
static void walk(DataDescriptorMatcher const &top, EDGEWALKER edgeWalker, LEAFWALKER leafWalker)
Marks an empty item in the context.
From https://en.cppreference.com/w/cpp/utility/variant/visit.
const std::byte * data() const noexcept
Definition DataHeader.h:422
the main header struct
Definition DataHeader.h:620
TFCounterType tfCounter
Definition DataHeader.h:681
TForbitType firstTForbit
Definition DataHeader.h:676
DataDescription dataDescription
Definition DataHeader.h:638
SubSpecificationType subSpecification
Definition DataHeader.h:658
RunNumberType runNumber
Definition DataHeader.h:686
a move-only header stack with serialized headers This is the flat buffer where all the headers in a m...
Definition Stack.h:33
VectorOfTObjectPtrs other