Skip to content

Commit

Permalink
pass the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Barthelemy committed Oct 12, 2023
1 parent a3c555a commit 08697fc
Show file tree
Hide file tree
Showing 3 changed files with 588 additions and 128 deletions.
243 changes: 177 additions & 66 deletions Framework/include/QualityControl/ptreeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,34 @@ using namespace std;
namespace o2::quality_control::core
{

namespace tree_ops
{
//namespace tree_ops
//{

/// @brief Walk a Boost.PropertyTree tree, invoking the binary function with
/// the full path and the current node.
template <typename Tree, typename Function>
void for_each(
const Tree& tree,
Function fn,
const typename Tree::path_type& parent_path = typename Tree::path_type(),
std::string fullpath="")
{
using path_type = typename Tree::path_type;
cout << "*** " << parent_path.dump() << endl;
for (auto&& value_pair : tree) {
cout << "*** '" << value_pair.first << "'" << endl;
cout << "*** fullpath: '" << fullpath << "'" << endl;
auto current_path = parent_path / path_type(value_pair.first);
// fn(current_path, value_pair.second);
std::string new_path = fullpath.empty() ? value_pair.first : fullpath+"."+value_pair.first;
fn(parent_path, path_type(value_pair.first), value_pair.second, new_path);
for_each(value_pair.second, fn, current_path, new_path);
}
}
// TODO when you get at an array this path is finished, just add the items and continue

// TODO what if we don't merge the trees and work with multiple ?ss
//
///// @brief Walk a Boost.PropertyTree tree, invoking the binary function with
///// the full path and the current node.
//template <typename Tree, typename Function>
//void for_each(
// const Tree& tree,
// Function fn,
// const typename Tree::path_type& parent_path = typename Tree::path_type(),
// std::string fullpath="")
//{
// using path_type = typename Tree::path_type;
// cout << "*** " << parent_path.dump() << endl;
// for (auto&& value_pair : tree) {
// cout << "*** '" << value_pair.first << "'" << endl;
// cout << "*** fullpath: '" << fullpath << "'" << endl;
// auto current_path = parent_path / path_type(value_pair.first);
// // fn(current_path, value_pair.second);
// std::string new_path = fullpath.empty() ? value_pair.first : fullpath+"."+value_pair.first;
// fn(parent_path, path_type(value_pair.first), value_pair.second, new_path);
// for_each(value_pair.second, fn, current_path, new_path);
// }
//}

/*/// @brief Return tree with elements in @ref s but not in @ref t.
template <typename Tree>
Expand All @@ -70,42 +74,42 @@ Tree tree_difference(const Tree& s, const Tree& t)
});
return result;
}*/

/// @brief Return tree with elements from both @ref s and @ref t.
template <typename Tree>
Tree tree_union(const Tree& s, const Tree& t)
{
// The result will always contain all values in @ref s.
Tree result = s;
// Iterate 't', add values to the result only if the node is
// either not in 's' or the values are different.
for_each(t,
[&](const typename Tree::path_type& parent_path, const typename Tree::path_type& this_path, const Tree& node, std::string fullpath) {
cout << "--------------------------" << endl;
cout << "tree_union parent_path : '" << parent_path.dump() << "' / '" << this_path.dump() << "' : " << node.data() << endl;
cout << "fullpath : " << fullpath << endl;
auto current_path = parent_path / this_path;
auto child = s.get_child_optional(current_path);

// if(child)
// cout << "tree_union : child.data : " << child->data() << endl;
// else
// cout << "tree_union : no child "<< endl;
if (!child || (child->data() != node.data())) {
if(this_path.empty()) {
cout << "EMPTY" << endl;
// special case when the key is empty. It is probably a comment ?
auto& result_parent= result.get_child(parent_path);
result_parent.push_back(ptree::value_type("", node.data()));
} else {
result.add(fullpath, node.data());
}
}
});
return result;
}

}
//
///// @brief Return tree with elements from both @ref s and @ref t.
//template <typename Tree>
//Tree tree_union(const Tree& s, const Tree& t)
//{
// // The result will always contain all values in @ref s.
// Tree result = s;
// // Iterate 't', add values to the result only if the node is
// // either not in 's' or the values are different.
// for_each(t,
// [&](const typename Tree::path_type& parent_path, const typename Tree::path_type& this_path, const Tree& node, std::string fullpath) {
// cout << "--------------------------" << endl;
// cout << "tree_union parent_path : '" << parent_path.dump() << "' / '" << this_path.dump() << "' : " << node.data() << endl;
// cout << "fullpath : " << fullpath << endl;
// auto current_path = parent_path / this_path;
// auto child = s.get_child_optional(current_path);
//
// // if(child)
// // cout << "tree_union : child.data : " << child->data() << endl;
// // else
// // cout << "tree_union : no child "<< endl;
// if (!child || (child->data() != node.data())) {
// if(this_path.empty()) {
// cout << "EMPTY" << endl;
// // special case when the key is empty. It is probably a comment ?
// auto& result_parent= result.get_child(parent_path);
// result_parent.push_back(ptree::value_type("", node.data()));
// } else {
// result.add(fullpath, node.data());
// }
// }
// });
// return result;
//}
//
//}

/*/// @brief Return tree with elements from both @ref s and @ref t.
template <typename Tree>
Expand Down Expand Up @@ -166,13 +170,13 @@ boost::property_tree::ptree operator-(
return tree_ops::tree_difference(lhs, rhs);
}*/

/// @brief Return tree with elements in both @ref lhs and @ref rhs.
boost::property_tree::ptree operator|(
const boost::property_tree::ptree& lhs,
const boost::property_tree::ptree& rhs)
{
return tree_ops::tree_union(lhs, rhs);
}
///// @brief Return tree with elements in both @ref lhs and @ref rhs.
//boost::property_tree::ptree operator|(
// const boost::property_tree::ptree& lhs,
// const boost::property_tree::ptree& rhs)
//{
// return tree_ops::tree_union(lhs, rhs);
//}

/*/// @brief Return tree with elements common to @ref lhs and @ref rhs.
boost::property_tree::ptree operator&(
Expand All @@ -191,6 +195,113 @@ boost::property_tree::ptree operator^(
return tree_ops::tree_symmetric_difference(lhs, rhs);
}*/


// Create necessary escape sequences from illegal characters
//template<class Ch>
//std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
//{
// std::basic_string<Ch> result;
// typename std::basic_string<Ch>::const_iterator b = s.begin();
// typename std::basic_string<Ch>::const_iterator e = s.end();
// while (b != e)
// {
// if (*b == Ch('\0')) result += Ch('\\'), result += Ch('0');
// else if (*b == Ch('\a')) result += Ch('\\'), result += Ch('a');
// else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
// else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
// else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
// else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
// else if (*b == Ch('\v')) result += Ch('\\'), result += Ch('v');
// else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"');
// else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
// else
// result += *b;
// ++b;
// }
// return result;
//}

// Freely inspired from write_json_helper in boost
template <class Ptree>
void mergeInto(const Ptree& pt, /*ptree& destination, */ptree& parent, const std::string& fullPath , int indent)
{
typedef typename Ptree::key_type::value_type Ch;
typedef typename std::basic_string<Ch> Str;

// Value or object or array
if (indent > 0 && pt.empty()) { // Handle value
Str data = /*create_escapes(*/pt.template get_value<Str>()/*)*/;
parent.add(fullPath, data);
} else if (indent > 0 && pt.count(Str()) == pt.size()) { // Handle array
typename Ptree::const_iterator it = pt.begin();
cout << "ARRAY " << endl;

// does the array exist in the destination ?
// ptree children;
// if ( parent.count(fullPath) > 0) {
// cout << " already exist in parent" << endl;
// children = parent.get_child(fullPath);
// } else {
// cout << " does not exist in parent" << endl;
// }

for (; it != pt.end(); ++it) {
ptree object;
// std::string newFullPath = fullPath.empty() ? it->first : fullPath + "." + it->first;
cout << " processing item :" << it->first << endl;
cout << " fullPath :" << fullPath << endl;
// cout << " newFullPath:" << newFullPath << endl;
// mergeInto(it->second, /*destination, */object, "", indent + 1);
// boost::property_tree::write_json(std::cout, object);
// cout << " object: " << endl;
// boost::property_tree::write_json(std::cout, it->second);
parent.add_child(fullPath+".", it->second);
// ptree test = object.get_child("").get_child("");
//
// if(test.empty())
// cout << "Node doesn't have children" << endl;
//
// if(test.data().empty())
// cout << "Node doesn't have data" << endl;
//
// if (object.empty() && !object.data().empty()) { // terminal
// cout << " terminal " << endl;
// children.put("", object.data());
// } else {
// cout << " not termianl " << endl;
// children.add_child("", object.get_child(""));
// }

// parent.add_child(fullPath, object);
// parent.add_child("", object);
}

// cout << " children:" << endl;
// boost::property_tree::write_json(std::cout, children);
//
// if ( parent.count(fullPath) == 0) {
// cout << " add to parent" << endl;
// parent.add_child(fullPath, children);
// }

// cout << " add to parent" << endl;
// TODO: check if array exist in parent, if so push_basck the object otherwise create it
// parent.add_child(fullPath, children);
} else { // Handle object
typename Ptree::const_iterator it = pt.begin();
for (; it != pt.end(); ++it) {
std::string newFullPath = fullPath.empty() ? it->first : fullPath + "." + it->first;
mergeInto(it->second, /*destination, */parent, newFullPath, indent + 1);
}
}
}

template <class Ptree>
void mergeInto(const Ptree& pt, ptree& destination)
{
mergeInto(pt, destination, destination, "", 1);
}

} // namespace o2::quality_control::test

#endif // QC_PTREE_UTILS_H
92 changes: 92 additions & 0 deletions Framework/src/runConfigMerger.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// 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 "QualityControl/Bookkeeping.h"
#include <iostream>
#include <boost/program_options.hpp>
#include "BookkeepingApi/BkpProtoClientFactory.h"
#include "QualityControl/Activity.h"
#include <Common/Timer.h>
#include "QualityControl/QcInfoLogger.h"

using namespace std;
namespace bpo = boost::program_options;
using namespace o2::bkp::api;
using namespace o2::bkp::api::proto;
using namespace o2::quality_control::core;

/**
* A small utility to stress test the bookkeeping api.
*/

int main(int argc, const char* argv[])
{
bpo::options_description desc{ "Options" };
desc.add_options()("help,h", "Help screen")("url,u", bpo::value<std::string>()->required(), "URL to the Bookkeeping")("run,r", bpo::value<int>())("max,m", bpo::value<int>()->default_value(10000), "Max number of executions, default: 10000")("printCycles,p", bpo::value<int>()->default_value(1000), "We print every X cycles, default: 1000")("printActivity", bpo::value<bool>()->default_value(false), "just to check that we get something in the activity.")("delay,d", bpo::value<int>()->default_value(0), "Minimum delay between calls in ms, default 0");

bpo::variables_map vm;
store(parse_command_line(argc, argv, desc), vm);

if (vm.count("help")) {
std::cout << desc << std::endl;
return 0;
}
notify(vm);

const auto url = vm["url"].as<string>();
cout << "url : " << url << endl;
const auto run = vm["run"].as<int>();
cout << "run : " << run << endl;
const auto max = vm["max"].as<int>();
cout << "max : " << max << endl;
const auto printCycles = vm["printCycles"].as<int>();
cout << "printCycles : " << printCycles << endl;
const auto printActivity = vm["printActivity"].as<bool>();
cout << "printActivity : " << printActivity << endl;
const auto minDelay = vm["delay"].as<int>();
cout << "minDelay : " << minDelay << endl;

ILOG_INST.filterDiscardDebug(true);
ILOG_INST.filterDiscardLevel(11);

Bookkeeping::getInstance().init(url);

AliceO2::Common::Timer timer;
AliceO2::Common::Timer triggerTimer;
triggerTimer.reset();
Activity activity;
double totalDuration = 0;
double cycleDuration = 0;
int numberOfExecutionsInCycle = 0;
int totalNumberOfExecutions = 0;

while (totalNumberOfExecutions < max) {
if (triggerTimer.isTimeout()) {
numberOfExecutionsInCycle++;
totalNumberOfExecutions++;
triggerTimer.reset(minDelay * 1000);
timer.reset();
Bookkeeping::getInstance().populateActivity(activity, run);
auto duration = timer.getTime();
if (printActivity) {
cout << activity << endl;
}
totalDuration += duration;
cycleDuration += duration;
if (totalNumberOfExecutions % printCycles == 0) {
cout << "average duration last " << printCycles << " calls in [ms]: " << cycleDuration / numberOfExecutionsInCycle * 1000 << endl;
numberOfExecutionsInCycle = 0;
cycleDuration = 0;
}
}
}
cout << "average duration overall in ms : " << totalDuration / totalNumberOfExecutions * 1000 << endl;
}
Loading

0 comments on commit 08697fc

Please sign in to comment.