Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Framework/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(SRCS
src/FairMQResizableBuffer.cxx
src/GraphvizHelpers.cxx
src/InputRecord.cxx
src/DataDescriptorQueryBuilder.cxx
src/LifetimeHelpers.cxx
src/LocalRootFileService.cxx
src/LogParsingHelpers.cxx
Expand Down
16 changes: 9 additions & 7 deletions Framework/Core/include/Framework/DataDescriptorMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ using Node = std::variant<OriginValueMatcher, DescriptionValueMatcher, SubSpecif
class DataDescriptorMatcher
{
public:
enum struct Op { Or,
enum struct Op { Just,
Or,
And,
Xor };

DataDescriptorMatcher(Node&& lhs, Op op, Node&& rhs)
/// Unary operator on a node
DataDescriptorMatcher(Op op, Node&& lhs, Node&& rhs = std::move(ConstantValueMatcher{ false }))
: mOp{ op },
mLeft{ std::move(lhs) },
mRight{ std::move(rhs) }
Expand All @@ -152,16 +154,16 @@ class DataDescriptorMatcher
return arg.match(d);
}
};
auto leftValue = std::visit(eval, mLeft);
auto rightValue = std::visit(eval, mRight);

switch (mOp) {
case Op::Or:
return leftValue || rightValue;
return std::visit(eval, mLeft) || std::visit(eval, mRight);
case Op::And:
return leftValue && rightValue;
return std::visit(eval, mLeft) && std::visit(eval, mRight);
case Op::Xor:
return leftValue ^ rightValue;
return std::visit(eval, mLeft) ^ std::visit(eval, mRight);
case Op::Just:
return std::visit(eval, mLeft);
}
};

Expand Down
42 changes: 42 additions & 0 deletions Framework/Core/include/Framework/DataDescriptorQueryBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright CERN and copyright holders of ALICE O2. This software is
// distributed under the terms of the GNU General Public License v3 (GPL
// Version 3), copied verbatim in the file "COPYING".
//
// See http://alice-o2.web.cern.ch/license for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#ifndef o2_framework_DataDescriptorQueryBuilder_H_INCLUDED
#define o2_framework_DataDescriptorQueryBuilder_H_INCLUDED

#include <string>
#include <vector>
#include <memory>

namespace o2
{
namespace framework
{

class DataDescriptorMatcher;

/// Various utilities to manipulate InputSpecs
struct DataDescriptorQueryBuilder {
/// Creates an inputspec from a configuration @a config string with the
/// following grammar.
///
/// string := [a-zA-Z0-9_]*
/// origin := string
/// description := string
/// subspec := [0-9]*
/// spec := origin/description/subspec
/// config := spec;spec;...
///
/// Example for config: TPC/CLUSTER/0;ITS/TRACKS/1
static std::shared_ptr<DataDescriptorMatcher> buildFromKeepConfig(std::string const& config);
};

} // namespace framework
} // namespace o2
#endif // o2_framework_DataDescriptorQueryBuilder_H_INCLUDED
62 changes: 62 additions & 0 deletions Framework/Core/src/DataDescriptorQueryBuilder.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright CERN and copyright holders of ALICE O2. This software is
// distributed under the terms of the GNU General Public License v3 (GPL
// Version 3), copied verbatim in the file "COPYING".
//
// See http://alice-o2.web.cern.ch/license for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#include "Framework/DataDescriptorQueryBuilder.h"
#include "Framework/DataDescriptorMatcher.h"

#include <memory>
#include <regex>
#include <string>
#include <vector>

namespace o2
{
namespace framework
{

std::shared_ptr<DataDescriptorMatcher> DataDescriptorQueryBuilder::buildFromKeepConfig(std::string const& config)
{
static const std::regex specTokenRE(R"re((\w{1,4})/(\w{1,16})/(\d*))re");
static const std::regex delimiter(",");

std::sregex_token_iterator iter(config.begin(),
config.end(),
delimiter,
-1);
std::sregex_token_iterator end;

std::unique_ptr<DataDescriptorMatcher> result;

for (; iter != end; ++iter) {
std::smatch m;
auto s = iter->str();
std::regex_match(s, m, specTokenRE);
std::unique_ptr<DataDescriptorMatcher> next;
auto newNode = std::make_unique<DataDescriptorMatcher>(
DataDescriptorMatcher::Op::And,
OriginValueMatcher{ m[1] },
std::make_unique<DataDescriptorMatcher>(
DataDescriptorMatcher::Op::And,
DescriptionValueMatcher{ m[2] },
SubSpecificationTypeValueMatcher{ m[3] }));
if (result.get() == nullptr) {
result = std::move(newNode);
} else {
next = std::move(std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Or,
std::move(result),
std::move(newNode)));
result = std::move(next);
}
}
return std::move(result);
}

} // namespace framework
} // namespace o2
71 changes: 64 additions & 7 deletions Framework/Core/test/test_DataDescriptorMatcher.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>
#include "Framework/DataDescriptorMatcher.h"
#include "Framework/DataDescriptorQueryBuilder.h"

#include <boost/test/unit_test.hpp>

using namespace o2::framework;
using namespace o2::header;
Expand Down Expand Up @@ -46,14 +48,14 @@ BOOST_AUTO_TEST_CASE(TestSimpleMatching)
header4.subSpecification = 0;

DataDescriptorMatcher matcher{
OriginValueMatcher{ "TPC" },
DataDescriptorMatcher::Op::And,
OriginValueMatcher{ "TPC" },
std::make_unique<DataDescriptorMatcher>(
DescriptionValueMatcher{ "CLUSTERS" },
DataDescriptorMatcher::Op::And,
DescriptionValueMatcher{ "CLUSTERS" },
std::make_unique<DataDescriptorMatcher>(
SubSpecificationTypeValueMatcher{ 1 },
DataDescriptorMatcher::Op::And,
SubSpecificationTypeValueMatcher{ 1 },
ConstantValueMatcher{ true }))
};

Expand All @@ -64,8 +66,8 @@ BOOST_AUTO_TEST_CASE(TestSimpleMatching)
BOOST_CHECK(matcher.match(header4) == false);

DataDescriptorMatcher matcher1{
OriginValueMatcher{ "TPC" },
DataDescriptorMatcher::Op::Or,
OriginValueMatcher{ "TPC" },
OriginValueMatcher{ "ITS" }
};

Expand All @@ -76,8 +78,7 @@ BOOST_AUTO_TEST_CASE(TestSimpleMatching)
BOOST_CHECK(matcher1.match(header4) == false);

DataDescriptorMatcher matcher2{
ConstantValueMatcher{ true },
DataDescriptorMatcher::Op::And,
DataDescriptorMatcher::Op::Just,
DescriptionValueMatcher{ "TRACKLET" }
};

Expand All @@ -87,3 +88,59 @@ BOOST_AUTO_TEST_CASE(TestSimpleMatching)
BOOST_CHECK(matcher2.match(header3) == false);
BOOST_CHECK(matcher2.match(header4) == true);
}

BOOST_AUTO_TEST_CASE(TestQueryBuilder)
{
DataHeader header0;
header0.dataOrigin = "TPC";
header0.dataDescription = "CLUSTERS";
header0.subSpecification = 1;

DataHeader header1;
header1.dataOrigin = "ITS";
header1.dataDescription = "TRACKLET";
header1.subSpecification = 2;

DataHeader header2;
header2.dataOrigin = "TPC";
header2.dataDescription = "TRACKLET";
header2.subSpecification = 1;

DataHeader header3;
header3.dataOrigin = "TPC";
header3.dataDescription = "CLUSTERS";
header3.subSpecification = 0;

DataHeader header4;
header4.dataOrigin = "TRD";
header4.dataDescription = "TRACKLET";
header4.subSpecification = 0;

auto matcher1 = DataDescriptorQueryBuilder::buildFromKeepConfig("TPC/CLUSTERS/1");
BOOST_CHECK(matcher1->match(header0) == true);
BOOST_CHECK(matcher1->match(header1) == false);
BOOST_CHECK(matcher1->match(header2) == false);
BOOST_CHECK(matcher1->match(header3) == false);
BOOST_CHECK(matcher1->match(header4) == false);

auto matcher2 = DataDescriptorQueryBuilder::buildFromKeepConfig("ITS/TRACKLET/2");
BOOST_CHECK(matcher2->match(header0) == false);
BOOST_CHECK(matcher2->match(header1) == true);
BOOST_CHECK(matcher2->match(header2) == false);
BOOST_CHECK(matcher2->match(header3) == false);
BOOST_CHECK(matcher2->match(header4) == false);

auto matcher3 = DataDescriptorQueryBuilder::buildFromKeepConfig("TPC/CLUSTERS/1,ITS/TRACKLET/2");
BOOST_CHECK(matcher3->match(header0) == true);
BOOST_CHECK(matcher3->match(header1) == true);
BOOST_CHECK(matcher3->match(header2) == false);
BOOST_CHECK(matcher3->match(header3) == false);
BOOST_CHECK(matcher3->match(header4) == false);

auto matcher4 = DataDescriptorQueryBuilder::buildFromKeepConfig("");
BOOST_CHECK(matcher4->match(header0) == false);
BOOST_CHECK(matcher4->match(header1) == false);
BOOST_CHECK(matcher4->match(header2) == false);
BOOST_CHECK(matcher4->match(header3) == false);
BOOST_CHECK(matcher4->match(header4) == false);
}