12#include <unordered_map>
46 type <<
" \"" << data <<
"\" is not found",
56 "object \'" << object_id <<
'@' << class_name <<
"\' was deleted",
58 ((const
char*)class_name)
59 ((const
char*)object_id)
65template <
typename T>
static T*
get_new(ConfigObject& co,
66 const std::string& attrname) {
68 co.get(attrname, *retval);
99 return (getenv(
"TDAQ_DB_PREFETCH_ALL_DATA") !=
nullptr);
116 if (const char *env = getenv(
"TDAQ_DB"))
125 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no database parameter found (check parameter of the constructor or value of TDAQ_DB environment variable)");
127 std::string::size_type idx =
m_impl_spec.find_first_of(
':');
129 if (idx == std::string::npos)
139 std::string plugin_name = std::string(
"lib") +
m_impl_name +
".so";
140 std::string impl_creator = std::string(
"_") +
m_impl_name +
"_creator_";
143 m_shlib_h = dlopen(plugin_name.c_str(), RTLD_LAZY | RTLD_GLOBAL);
147 std::ostringstream text;
148 text <<
"failed to load implementation plug-in \'" << plugin_name <<
"\': \"" << dlerror() <<
'\"';
149 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str() ) );
155 (*f)(
const std::string& spec);
158 (*)(
const std::string&))dlsym(
m_shlib_h, impl_creator.c_str());
162 if ((
error = dlerror()) != 0)
164 std::ostringstream text;
165 text <<
"failed to find implementation creator function \'" << impl_creator <<
"\' in plug-in \'" << plugin_name <<
"\': \"" <<
error <<
'\"';
166 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str() ) );
183 m_impl->prefetch_all_data();
185 TLOG_DEBUG(2) <<
"\n*** DUMP CONFIGURATION ***\n" << *
this;
192 std::lock_guard < std::mutex > scoped_lock(
m_impl_mutex);
194 std::cout <<
"Configuration profiler report:\n"
216 m_impl->print_cache_info();
217 m_impl->print_profiling_info();
223 if (::getenv(
"TDAQ_DUMP_CONFFWK_PROFILER_INFO"))
240 catch (dunedaq::conffwk::Generic& ex)
250 _get(class_name,
id,
object, rlevel, rclasses);
254Configuration::_get(
const std::string& class_name,
const std::string& name,
ConfigObject&
object,
unsigned long rlevel,
const std::vector<std::string> * rclasses)
258 m_impl->
get(class_name, name,
object, rlevel, rclasses);
260 catch (dunedaq::conffwk::Generic& ex)
262 std::ostringstream text;
263 text <<
"failed to get object \'" << name <<
'@' << class_name <<
'\'';
264 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
269Configuration::get(
const std::string& class_name, std::vector<ConfigObject>& objects,
const std::string& query,
unsigned long rlevel,
const std::vector<std::string> * rclasses)
274 m_impl->get(class_name, objects, query, rlevel, rclasses);
276 catch (dunedaq::conffwk::Generic& ex)
278 std::ostringstream text;
279 text <<
"failed to get objects of class \'" << class_name <<
'\'';
282 text <<
" with query \'" << query <<
'\'';
284 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
289Configuration::get(
const ConfigObject& obj_from,
const std::string& query, std::vector<ConfigObject>& objects,
unsigned long rlevel,
const std::vector<std::string> * rclasses)
294 m_impl->get(obj_from, query, objects, rlevel, rclasses);
296 catch (dunedaq::conffwk::Generic& ex)
298 std::ostringstream text;
299 text <<
"failed to get path \'" << query <<
"\' from object \'" << obj_from <<
'\'';
300 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
323 const char * s = ::getenv(
"TDAQ_DB_NAME");
324 if (s == 0 || *s == 0)
325 s = ::getenv(
"TDAQ_DB_DATA");
333 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"no database name was provided" ) );
363 m_impl->prefetch_all_data();
366 TLOG_DEBUG(2) <<
"\n*** DUMP CONFIGURATION ***\n" << *
this;
370 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
378 throw dunedaq::conffwk::Generic(
ERS_HERE,
"nothing to unload" );
414 for (
auto& a : *l.second)
441 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
447 m_impl->create(db_name, includes);
450 catch(dunedaq::conffwk::Generic & ex)
452 std::ostringstream text;
453 text <<
"failed to create database \'" << db_name <<
'\'';
454 throw ( dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex ) );
463 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" ) );
469 return m_impl->is_writable(db_name);
471 catch(dunedaq::conffwk::Generic & ex)
473 std::ostringstream text;
474 text <<
"failed to get write access status for database \'" << db_name<<
'\'';
475 throw ( dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex ) );
484 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
490 m_impl->add_include(db_name, include);
495 catch(dunedaq::conffwk::Generic & ex)
497 std::ostringstream text;
498 text <<
"failed to add include \'" << include <<
"\' to database \'" << db_name<<
'\'';
499 throw ( dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex ) );
507 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
514 m_impl->remove_include(db_name, include);
519 catch(dunedaq::conffwk::Generic & ex)
521 std::ostringstream text;
522 text <<
"failed to remove include \'" << include <<
"\' from database \'" << db_name<<
'\'';
523 throw ( dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex ) );
531 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
537 m_impl->get_includes(db_name, includes);
539 catch(dunedaq::conffwk::Generic & ex)
541 std::ostringstream text;
542 text <<
"failed to get includes of database \'" << db_name<<
'\'';
543 throw ( dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex ) );
552 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
558 m_impl->get_updated_dbs(dbs);
560 catch(dunedaq::conffwk::Generic & ex)
562 throw ( dunedaq::conffwk::Generic(
ERS_HERE,
"get_updated_dbs failed", ex ) );
571 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded" );
577 m_impl->set_commit_credentials(user, password);
579 catch(dunedaq::conffwk::Generic & ex)
581 throw ( dunedaq::conffwk::Generic(
ERS_HERE,
"set_commit_credentials failed", ex ) );
592 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
599 m_impl->commit(log_message);
601 catch (dunedaq::conffwk::Generic & ex)
603 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"commit failed", ex ) );
613 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
628 catch (dunedaq::conffwk::Generic & ex)
630 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"abort failed", ex));
642 m_impl->prefetch_all_data();
644 catch (dunedaq::conffwk::Generic & ex)
646 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"prefetch all data failed", ex));
653 if (unread_implementation_objs)
670 for (
auto &i :
m_impl->m_impl_objects)
671 for (
auto &j : *i.second)
673 std::lock_guard<std::mutex> scoped_lock(j.second->m_mutex);
675 j.second->m_state = state;
678 for (
auto& x :
m_impl->m_tangled_objects)
680 std::lock_guard<std::mutex> scoped_lock(x->m_mutex);
693 for (
const auto &j : i.second)
708std::deque<std::set<std::string>>
711 std::deque<std::set<std::string>> domains;
713 std::deque<dunedaq::conffwk::class_t> seeds;
716 if (ci.p_superclasses.empty())
720 for (
const auto& ci : seeds) {
722 std::set<std::string> class_domain;
723 class_domain.insert(ci.p_name);
724 class_domain.insert(ci.p_subclasses.begin(), ci.p_subclasses.end());
727 std::deque<std::set<std::string>> overlapping;
728 for (
auto& d : domains) {
729 std::set<std::string> intersection;
730 std::set_intersection(d.begin(), d.end(), class_domain.begin(), class_domain.end(), std::inserter(intersection, intersection.begin()));
732 if (intersection.size() > 0) {
733 overlapping.push_back(d);
739 if ( !overlapping.empty() ) {
740 for(
auto& d : overlapping ) {
742 class_domain.insert(d.begin(), d.end());
744 auto it = std::find(domains.begin(), domains.end(), d);
745 if (it!= domains.end()) {
751 domains.push_back(class_domain);
764 for(
size_t i(0); i<domains.size(); ++i ) {
765 const auto& dom = domains[i];
766 for(
const auto& class_name : dom ) {
767 p_class_domain_map[&conffwk::DalFactory::instance().get_known_class_name_ref(class_name)] = i;
782Configuration::test_object(
const std::string& class_name,
const std::string&
id,
unsigned long rlevel,
const std::vector<std::string> * rclasses)
787 return m_impl->test_object(class_name,
id, rlevel, rclasses);
789 catch (dunedaq::conffwk::Generic& ex)
791 std::ostringstream text;
792 text <<
"failed to test existence of object \'" <<
id <<
'@' << class_name <<
'\'';
793 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
803 m_impl->create(at, class_name,
id,
object);
805 catch (dunedaq::conffwk::Generic& ex)
807 std::ostringstream text;
808 text <<
"failed to create object \'" <<
id <<
'@' << class_name <<
'\'';
809 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
819 m_impl->create(at, class_name,
id,
object);
821 catch (dunedaq::conffwk::Generic& ex)
823 std::ostringstream text;
824 text <<
"failed to create object \'" <<
id <<
'@' << class_name <<
'\'';
825 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
839 catch (dunedaq::conffwk::Generic& ex)
841 std::ostringstream text;
842 text <<
"failed to destroy object \'" <<
object <<
'\'';
843 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
851 std::lock_guard<std::mutex> scoped_impl_lock(
m_tmpl_mutex);
852 std::lock_guard<std::mutex> scoped_tmpl_lock(
m_impl_mutex);
854 std::lock_guard<std::mutex> scoped_obj_lock(
obj.m_impl->m_mutex);
856 const std::string old_id(
obj.m_impl->m_id);
858 obj.m_impl->throw_if_deleted();
859 obj.m_impl->rename(new_id);
860 obj.m_impl->m_id = new_id;
861 m_impl->rename_impl_object(
obj.m_impl->m_class_name, old_id, new_id);
863 TLOG_DEBUG(3) <<
" * call rename \'" << old_id <<
"\' to \'" << new_id <<
"\' in class \'" <<
obj.class_name() <<
"\')";
908 if (i != d_cache.end())
914 d_cache[class_name] = d;
918 catch (dunedaq::conffwk::Generic& ex)
920 std::ostringstream text;
921 text <<
"failed to get description of class \'" << class_name <<
'\'';
922 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex );
929init_regex(std::unique_ptr<std::regex>& ptr,
const std::string& str,
const char * what)
934 ptr = std::make_unique<std::regex>(str);
936 catch (
const std::regex_error &ex)
938 std::ostringstream text;
939 text <<
"failed to create " << what <<
" regex \"" << str <<
"\": " << ex.what();
940 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str());
949 boost::property_tree::ptree child;
951 pt.push_back(std::make_pair(
"", child));
957 std::unique_ptr<std::regex> classes_regex;
959 init_regex(classes_regex, classes_str,
"classes");
961 auto cmp_str_ptr = [](
const std::string * s1,
const std::string * s2) {
return *s1 < *s2; };
962 std::set<
const std::string *,
decltype(cmp_str_ptr)> sorted_classes(cmp_str_ptr);
965 if (classes_str.empty() || std::regex_match(*c.first, *classes_regex.get()))
966 sorted_classes.insert(c.first);
968 for (
const auto &c : sorted_classes)
969 if (classes_str.empty() || std::regex_match(*c, *classes_regex.get()))
973 boost::property_tree::ptree class_pt;
975 class_pt.put(
"abstract", info.p_abstract);
976 if (!info.p_description.empty())
977 class_pt.put(
"description", info.p_description);
979 if (!info.p_superclasses.empty())
983 for (
const auto &x : info.p_superclasses)
989 if (!info.p_attributes.empty())
991 boost::property_tree::ptree attributes;
993 for (
const auto &x : info.p_attributes)
995 boost::property_tree::ptree attribute;
998 if (!x.p_range.empty())
999 attribute.put(
"range", x.p_range);
1002 if (x.p_is_not_null)
1003 attribute.put(
"is-not-null", x.p_is_not_null);
1004 if (x.p_is_multi_value)
1005 attribute.put(
"is-multi-value", x.p_is_multi_value);
1006 if (!x.p_default_value.empty())
1007 attribute.put(
"default-value", x.p_default_value);
1008 if (!x.p_description.empty())
1009 attribute.put(
"description", x.p_description);
1011 attributes.push_back(boost::property_tree::ptree::value_type(x.p_name, attribute));
1014 class_pt.add_child(
"attributes", attributes);
1017 if (!info.p_relationships.empty())
1019 boost::property_tree::ptree relationships;
1021 for (
const auto &x : info.p_relationships)
1023 boost::property_tree::ptree relationship;
1025 relationship.put(
"type", x.p_type);
1027 if (!x.p_is_aggregation)
1028 relationship.put(
"is-aggregation", x.p_is_aggregation);
1029 if (!x.p_description.empty())
1030 relationship.put(
"description", x.p_description);
1032 relationships.push_back(boost::property_tree::ptree::value_type(x.p_name, relationship));
1035 class_pt.add_child(
"relationships", relationships);
1038 pt.put_child(boost::property_tree::ptree::path_type(*c), class_pt);
1046 auto &o =
const_cast<ConfigObject&
>(
obj);
1047 if (!attribute.p_is_multi_value)
1050 const_cast<ConfigObject&
>(
obj).get(attribute.p_name, val);
1051 pt.put(attribute.p_name, val);
1055 std::vector<T> values;
1056 o.get(attribute.p_name, values);
1058 boost::property_tree::ptree children;
1060 if (!values.empty())
1061 for (
const auto &
v : values)
1064 else if (!empty_array_item.empty())
1067 pt.add_child(attribute.p_name, children);
1076 std::vector<ConfigObject> values;
1077 const_cast<ConfigObject&
>(
obj).get(relationship.
p_name, values);
1079 boost::property_tree::ptree children;
1081 if (!values.empty())
1082 for (
const auto &
v : values)
1085 else if (!empty_array_item.empty())
1088 pt.add_child(relationship.
p_name, children);
1093 const_cast<ConfigObject&
>(
obj).get(relationship.
p_name, val);
1094 pt.put(relationship.
p_name, !val.is_null() ? val.full_name() :
"");
1099Configuration::export_data(boost::property_tree::ptree& pt,
const std::string& classes_str,
const std::string& objects_str,
const std::string& files_str,
const std::string& empty_array_item)
1101 std::unique_ptr<std::regex> classes_regex, objects_regex, files_regex;
1103 init_regex(classes_regex, classes_str,
"classes");
1104 init_regex(objects_regex, objects_str,
"objects");
1107 auto cmp_str_ptr = [](
const std::string * s1,
const std::string * s2) {
return *s1 < *s2; };
1108 std::set<
const std::string *,
decltype(cmp_str_ptr)> sorted_classes(cmp_str_ptr);
1111 if (classes_str.empty() || std::regex_match(*c.first, *classes_regex.get()))
1112 sorted_classes.insert(c.first);
1114 for (
const auto &c : sorted_classes)
1115 if (classes_str.empty() || std::regex_match(*c, *classes_regex.get()))
1119 boost::property_tree::ptree pt_objects;
1121 std::vector<ConfigObject> objects;
1125 std::set<
const ConfigObject *,
decltype(comp_obj_ptr)> sorted_objects(comp_obj_ptr);
1127 for (
const auto& x : objects)
1128 if (objects_str.empty() || std::regex_match(x.UID(), *objects_regex.get()))
1129 if (x.class_name() == *c)
1130 if(files_str.empty() || std::regex_match(x.contained_in(), *files_regex.get()))
1131 sorted_objects.insert(&x);
1133 if (!sorted_objects.empty())
1135 boost::property_tree::ptree pt_objects;
1137 for (
const auto& x : sorted_objects)
1139 boost::property_tree::ptree data;
1141 for (
const auto &a : info.p_attributes)
1185 throw std::runtime_error(
"Invalid type of attribute " + a.p_name);
1189 for (
const auto &r : info.p_relationships)
1190 add_data(data, *x, r, empty_array_item);
1192 pt_objects.push_back(boost::property_tree::ptree::value_type(x->UID(), data));
1195 pt.put_child(boost::property_tree::ptree::path_type(*c), pt_objects);
1209std::vector<dunedaq::conffwk::Version>
1215 return m_impl->get_changes();
1217 catch (dunedaq::conffwk::Generic& ex)
1219 throw dunedaq::conffwk::Generic(
ERS_HERE,
"failed to get new versions", ex );
1224std::vector<dunedaq::conffwk::Version>
1230 return m_impl->get_versions(since, until,
type, skip_irrelevant);
1232 catch (dunedaq::conffwk::Generic& ex)
1234 throw dunedaq::conffwk::Generic(
ERS_HERE,
"failed to get versions", ex );
1263 throw dunedaq::conffwk::Generic(
ERS_HERE,
"callback function is not defined" );
1268 Configuration::CallbackSubscription * cs =
new CallbackSubscription();
1270 cs->m_criteria = criteria;
1272 cs->m_param = parameter;
1284 catch (dunedaq::conffwk::Generic& ex)
1288 throw dunedaq::conffwk::Generic(
ERS_HERE,
"subscription failed", ex );
1298 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"callback function is not defined" ) );
1305 cs->m_param = parameter;
1319 std::lock_guard < std::mutex > scoped_lock(
m_else_mutex);
1338 std::ostringstream text;
1339 text <<
"unsubscription failed for CallbackId = " << (
void *)
id <<
" (no such callback id found)";
1340 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str() ) );
1359 catch (dunedaq::conffwk::Generic& ex)
1361 throw dunedaq::conffwk::Generic(
ERS_HERE,
"unsubscription failed", ex );
1380 std::set<std::string> class_subscriptions;
1384 bool found_subscribe_all =
false;
1387 if (i->m_criteria.get_classes_subscription().empty() && i->m_criteria.get_objects_subscription().empty())
1389 found_subscribe_all =
true;
1393 if (found_subscribe_all ==
false)
1397 for (
const auto &j : i->m_criteria.get_classes_subscription())
1398 class_subscriptions.insert(j);
1402 for (
const auto &j : i->m_criteria.get_objects_subscription())
1404 const std::string &obj_class_name = j.first;
1405 if (class_subscriptions.find(obj_class_name) == class_subscriptions.end())
1406 for (
const auto &k : j.second)
1407 obj_subscriptions[obj_class_name].insert(k);
1422 if (i != cache.end())
1427 if (j != i->second->end())
1429 TLOG_DEBUG( 2 ) <<
"set implementation object " << x <<
'@' << *class_name <<
" [" << (
void *)j->second <<
"] deleted";
1431 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1443 if (i != cache.end())
1448 if (j != i->second->end())
1450 TLOG_DEBUG( 2 ) <<
"re-set created implementation object " << x <<
'@' << *class_name <<
" [" << (
void *)j->second <<
']';
1452 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1463 if (i != cache.end())
1468 if (j != i->second->end())
1470 TLOG_DEBUG(2) <<
"clear implementation object " << x <<
'@' << *class_name <<
" [" << (
void *)j->second <<
']';
1472 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1490 TLOG_DEBUG(3) <<
"*** Enter Configuration::update_cache() with changes:\n" << changes;
1493 for (
const auto& i : changes)
1495 const std::string * class_name = &DalFactory::instance().get_known_class_name_ref(i->get_class_name());
1503 for (
const auto &c : sc->second)
1510 for (
const auto &c : sc->second)
1514 for (
const auto& i : changes)
1517 m_registry.update(i->get_class_name(), i->get_modified_objs(), i->get_removed_objs(), i->get_created_objs());
1585 "*** Enter Configuration::system_cb()\n"
1586 "*** Number of user subscriptions: " << conf->m_callbacks.size()
1591 std::lock_guard<std::mutex> scoped_lock(conf->m_impl_mutex);
1592 std::lock_guard<std::mutex> scoped_lock2(conf->m_actn_mutex);
1593 for (
auto & i : conf->m_actions)
1600 std::lock_guard<std::mutex> scoped_lock(conf->m_tmpl_mutex);
1601 std::lock_guard<std::mutex> scoped_lock2(conf->m_impl_mutex);
1602 conf->update_cache(changes);
1607 if(conf->m_callbacks.empty())
return;
1612 std::lock_guard<std::mutex> scoped_lock(conf->m_else_mutex);
1615 if (conf->m_callbacks.size() == 1)
1617 auto j = *conf->m_callbacks.begin();
1618 (*(j->m_cb))(changes, j->m_param);
1623 for (
const auto &j : conf->m_callbacks)
1628 std::ostringstream text;
1631 "*** Process subscription " << (
void*) j <<
"\n"
1632 " class subscription done for " << j->m_criteria.get_classes_subscription().size() <<
" classes:\n";
1634 for (
const auto &i1 : j->m_criteria.get_classes_subscription())
1635 text <<
" * class \"" << i1 <<
"\"\n";
1637 text <<
" object subscription done in " << j->m_criteria.get_objects_subscription().size() <<
" classes:\n";
1639 for (
const auto &i2 : j->m_criteria.get_objects_subscription())
1641 text <<
" * class \"" << (i2.first) <<
"\":\n";
1642 for (
const auto &i3 : i2.second)
1643 text <<
" - \"" << i3 <<
"\"\n";
1649 if (j->m_criteria.get_classes_subscription().empty() && j->m_criteria.get_objects_subscription().empty())
1653 TLOG_DEBUG(3) <<
"*** Invoke callback " << (
void *)j <<
" with\n" << changes;
1654 (*(j->m_cb))(changes, j->m_param);
1658 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown ers exception", ex));
1660 catch (
const std::exception &ex)
1662 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown std exception", ex));
1666 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown unknown exception"));
1671 std::vector<ConfigurationChange*> changes1;
1673 for (
const auto &i : changes)
1675 const std::string &cname = i->get_class_name();
1678 ConfigurationSubscriptionCriteria::ObjectMap::const_iterator p = j->m_criteria.get_objects_subscription().find(cname);
1679 const bool found_obj_subscription(p != j->m_criteria.get_objects_subscription().end());
1680 const bool found_class_subscription(j->m_criteria.get_classes_subscription().find(cname) != j->m_criteria.get_classes_subscription().end());
1682 if (found_class_subscription || found_obj_subscription)
1685 if (found_class_subscription)
1687 for (
const auto &k : i->m_modified)
1690 for (
const auto &k : i->m_created)
1693 for (
const auto &k : i->m_removed)
1697 if (found_obj_subscription)
1699 for (
const auto &obj_id : i->m_modified)
1700 if (p->second.find(obj_id) != p->second.end())
1703 for (
const auto &obj_id : i->m_removed)
1704 if (p->second.find(obj_id) != p->second.end())
1705 class_changes->
m_removed.push_back(obj_id);
1712 delete class_changes;
1714 changes1.push_back(class_changes);
1718 if (!changes1.empty())
1720 TLOG_DEBUG(3) <<
"*** Invoke callback " << (
void *)j <<
" with\n" << changes1;
1724 (*(j->m_cb))(changes1, j->m_param);
1728 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown ers exception", ex));
1730 catch (
const std::exception &ex)
1732 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown std exception", ex));
1736 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown unknown exception"));
1739 for (
const auto &i : changes1)
1746 TLOG_DEBUG(3) <<
"*** Leave Configuration::system_cb()";
1753 TLOG_DEBUG(3) <<
"*** Enter Configuration::system_pre_cb()";
1755 std::lock_guard<std::mutex> scoped_lock(conf->m_else_mutex);
1757 for(
auto& j : conf->m_pre_callbacks)
1759 TLOG_DEBUG(3) <<
"*** Invoke callback " << (
void *)(j);
1760 (*(j->m_cb))(j->m_param);
1763 TLOG_DEBUG(3) <<
"*** Leave Configuration::system_pre_cb()";
1768ConfigurationChange::add(std::vector<ConfigurationChange*> &changes,
const std::string &class_name,
const std::string &obj_name,
const char action)
1772 for (
const auto &c : changes)
1773 if (class_name == c->get_class_name())
1782 changes.push_back(class_changes);
1785 std::vector<std::string>& clist = (
1786 action ==
'+' ? class_changes->
m_created :
1787 action ==
'-' ? class_changes->
m_removed :
1791 clist.push_back(obj_name);
1798 for (
const auto &i : changes)
1806print_svect(std::ostream& s,
const std::vector<std::string>&
v,
const char * name)
1808 s <<
" * " <<
v.size() << name;
1810 for (
auto i =
v.begin(); i !=
v.end(); ++i)
1812 s << ((i ==
v.begin()) ?
": " :
", ");
1813 s <<
'\"' << *i <<
'\"';
1821operator<<(std::ostream &s,
const ConfigurationChange &c)
1823 s <<
" changes for class \'" << c.get_class_name() <<
"\' include:\n";
1825 print_svect(s, c.get_modified_objs(),
" modified object(s)");
1826 print_svect(s, c.get_created_objs(),
" created object(s)");
1827 print_svect(s, c.get_removed_objs(),
" removed object(s)");
1834operator<<(std::ostream &s,
const std::vector<ConfigurationChange*> &
v)
1836 s <<
"There are configuration changes in " <<
v.size() <<
" classes:\n";
1838 for (
const auto &i :
v)
1847 s <<
"Configuration object:\n Inheritance Hierarchy (class - all it's superclasses):\n";
1851 s <<
" * \'" << *i.first <<
"\' - ";
1852 if (i.second.empty())
1855 for (
auto j = i.second.begin(); j != i.second.end(); ++j)
1857 if (j != i.second.begin())
1859 s <<
'\'' << **j <<
'\'';
1881 return is_superclass_of(&DalFactory::instance().get_known_class_name_ref(base_class), &DalFactory::instance().get_known_class_name_ref(child_class));
1887 if (base_class == child_class)
1889 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is allowed (equal classes)";
1893 conffwk::fmap<conffwk::fset>::iterator i = p_superclasses.find(child_class);
1895 if (i == p_superclasses.end())
1897 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is not possible (base class is not loaded)";
1901 if (i->second.find(base_class) != i->second.end())
1903 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is allowed (use inheritance)";
1907 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is not allowed (class \'" << *child_class <<
"\' has no \'" << *base_class <<
"\' as a superclass)";
1914operator<<(std::ostream &s,
const Configuration &c)
1949 std::ostringstream text;
1950 text <<
"failed to get " << what <<
" of class \'" << cname <<
"\' via relationship \'" << rname <<
"\' of object \'" <<
obj <<
'\'';
1958 std::ostringstream text;
1959 text <<
"failed to get objects of class \'" << cname <<
"\' referencing object \'" <<
obj <<
"\' via relationship \'" << rname <<
'\'';
1984std::vector<const DalObject*>
1986 bool check_composite_only,
bool upcast_unregistered,
1987 bool ,
unsigned long rlevel,
1988 const std::vector<std::string> * rclasses)
1992 std::vector<ConfigObject> objs;
1995 obj.p_obj.referenced_by(objs, relationship_name, check_composite_only, rlevel, rclasses);
1999 catch (dunedaq::conffwk::Generic & ex)
2005std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
2008 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> all_attributes_properties;
2012 for (
const auto& ap : c.p_attributes) {
2013 std::unordered_map<std::string, std::string> attribute_properties;
2016 attribute_properties[
"range"] = ap.p_range.empty() ?
"None" : ap.p_range;
2018 attribute_properties[
"description"] = ap.p_description;
2020 attribute_properties[
"multivalue"] = ap.p_is_multi_value ?
"True" :
"False";
2022 attribute_properties[
"not-null"] = ap.p_is_not_null ?
"True" :
"False";
2024 attribute_properties[
"init-value"] = ap.p_default_value.empty() ?
"None" : ap.p_default_value;
2026 all_attributes_properties[ap.p_name] = attribute_properties;
2029 return all_attributes_properties;
2032std::vector<std::string>
2034 std::vector<std::string> classes;
2036 classes.push_back(*it.first);
2045 this->
create(at, class_name,
id, *co);
2053 this->
create(at, class_name,
id, *co);
2061 this->
get(class_name,
id, *co);
2062 if (co->is_null()) {
2069std::vector<ConfigObject>*
2071 auto objs =
new std::vector<ConfigObject>;
2072 this->
get(class_name, *objs, query);
2077std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
2080 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> all_relationships_properties;
2084 for (
const auto& rp : c.p_relationships) {
2085 std::unordered_map<std::string, std::string> relationship_properties;
2087 relationship_properties[
"type"] = rp.p_type;
2088 relationship_properties[
"description"] = rp.p_description;
2090 relationship_properties[
"aggregation"] = rp.p_is_aggregation ?
"True" :
"False";
2093 all_relationships_properties[rp.p_name] = relationship_properties;
2096 return all_relationships_properties;
2099std::list<std::string>*
2101 auto l =
new std::list<std::string>;
2106std::vector<std::string>
2110 return c.p_subclasses;
2113std::vector<std::string>
2117 return c.p_superclasses;
2123 return c.p_schema_path;
#define ERS_DEFINE_ISSUE_CXX(namespace_name, class_name, message, attributes)
Represents database objects.
const std::string & UID() const noexcept
Return object identity.
Describes changes inside a class returned by the notification mechanism.
const std::vector< std::string > & get_created_objs() const
Return vector of identies of created objects.
std::vector< std::string > m_removed
static void clear(std::vector< ConfigurationChange * > &changes)
Helper method to clear vector of changes (pointers).
ConfigurationChange(const ConfigurationChange &)
std::vector< std::string > m_created
std::vector< std::string > m_modified
static void add(std::vector< ConfigurationChange * > &changes, const std::string &class_name, const std::string &obj_id, const char action)
Helper method to add object to the vector of existing changes.
const std::vector< std::string > & get_modified_objs() const
Return vector of identies of modified objects.
const std::vector< std::string > & get_removed_objs() const
Return vector of identies of removed objects.
virtual void get(const std::string &class_name, const std::string &id, ConfigObject &object, unsigned long rlevel, const std::vector< std::string > *rclasses)=0
Get object of class by id.
Describes a subscription criteria.
std::map< std::string, std::set< std::string > > ObjectMap
The map stores full subsription information.
void update_cache(std::vector< ConfigurationChange * > &changes) noexcept
System function invoked in case of modifications.
std::vector< ConfigObject > * get_objs_pybind(const std::string &class_name, const std::string &query="")
void _get(const std::string &class_name, const std::string &id, ConfigObject &object, unsigned long rlevel, const std::vector< std::string > *rclasses)
const conffwk::fmap< conffwk::fset > & superclasses() const noexcept
static void update_impl_objects(conffwk::pmap< conffwk::map< ConfigObjectImpl * > * > &cache, ConfigurationChange &change, const std::string *class_name)
void set_subclasses() noexcept
conffwk::map< std::list< AttributeConverterBase * > * > m_convert_map
void get(const std::string &class_name, const std::string &id, ConfigObject &object, unsigned long rlevel=0, const std::vector< std::string > *rclasses=0)
Get object by class name and object id (multi-thread safe).
void _unread_implementation_objects(dunedaq::conffwk::ObjectState state) noexcept
ConfigurationImpl * m_impl
friend class ConfigObject
static void system_cb(std::vector< ConfigurationChange * > &, Configuration *) noexcept
System callback function invoked in case of modifications.
std::unordered_map< std::string, std::unordered_map< std::string, std::string > > attributes_pybind(const std::string &class_name, bool all)
void destroy_obj(ConfigObject &object)
Destroy object.
std::unordered_map< std::string, std::unordered_map< std::string, std::string > > relations_pybind(const std::string &class_name, bool all)
void reset_subscription()
void remove_include(const std::string &db_name, const std::string &include)
Remove include file.
void get_updated_dbs(std::list< std::string > &dbs) const
Get list of updated files to be committed.
PreCallbackSet m_pre_callbacks
void prefetch_all_data()
Prefetch all data into client cache.
void load(const std::string &db_name)
Load database according to the name. If name is empty, take it from TDAQ_DB_NAME and TDAQ_DB_DATA env...
Configuration(const std::string &spec)
Constructor to build a configuration object using implementation plug-in.
void action_on_update(const ConfigObject &obj, const std::string &name)
void remove_action(ConfigAction *ac)
bool is_writable(const std::string &db_name) const
Get write access status.
std::list< ConfigAction * > m_actions
void set_commit_credentials(const std::string &user, const std::string &password)
Set commit credentials.
void print(std::ostream &) const noexcept
Prints out details of configuration object.
~Configuration() noexcept
Destructor to destroy a configuration object.
void add_action(ConfigAction *ac)
std::atomic< uint_least64_t > p_number_of_template_object_created
void unread_template_objects() noexcept
Unread all template (i.e. set their state as uninitialized) objects.
void update_classes() noexcept
static void system_pre_cb(Configuration *) noexcept
System callback function invoked in case of pre-modifications.
conffwk::fmap< conffwk::fset > p_subclasses
void referenced_by(const T &obj, std::vector< const V * > &objects, const std::string &relationship_name="*", bool check_composite_only=true, bool init=false, unsigned long rlevel=0, const std::vector< std::string > *rclasses=nullptr)
Get template DAL objects holding references on this object via given relationship (multi-thread safe)...
std::vector< std::string > superclasses_pybind(const std::string &class_name, bool all)
CallbackSubscription * find_callback(CallbackId cb_handler) const
void create(const std::string &at, const std::string &class_name, const std::string &id, ConfigObject &object)
Create new object by class name and object id.
static std::string mk_ref_ex_text(const char *what, const std::string &cname, const std::string &rname, const ConfigObject &obj) noexcept
CallbackSubscription * CallbackId
Callback identifier.
const dunedaq::conffwk::class_t & _get_class_info(const std::string &class_name, bool direct_only=false)
std::vector< std::string > subclasses_pybind(const std::string &class_name, bool all)
std::list< std::string > * return_includes_pybind(const std::string &db_name)
bool loaded() const noexcept
Check if database is correctly loaded.
friend class ConfigurationImpl
std::vector< std::string > get_class_list() const
conffwk::map< dunedaq::conffwk::class_t * > p_all_classes_desc_cache
void set_class_domain_map()
void unread_all_objects(bool unread_implementation_objs=false) noexcept
Unread all template (i.e. set their state as uninitialized) and implementation objects (i....
std::deque< std::set< std::string > > find_class_domains()
const std::string & get_schema_path_pybind(const std::string &class_name)
const dunedaq::conffwk::class_t & get_class_info(const std::string &class_name, bool direct_only=false)
The method provides access to description of class.
void get_includes(const std::string &db_name, std::list< std::string > &includes) const
Get include files.
conffwk::fmap< conffwk::fset > p_superclasses
std::vector< dunedaq::conffwk::Version > get_changes()
Get new conffwk versions.
conffwk::map< dunedaq::conffwk::class_t * > p_direct_classes_desc_cache
void commit(const std::string &log_message="")
Commit database changes.
conffwk::fmap< uint > p_class_domain_map
bool is_superclass_of(const std::string &target, const std::string &source) noexcept
void _unread_template_objects() noexcept
void export_data(boost::property_tree::ptree &tree, const std::string &classes="", const std::string &objects="", const std::string &files="", const std::string &empty_array_item="")
Export configuration data into ptree.
static std::string mk_ref_by_ex_text(const std::string &cname, const std::string &rname, const ConfigObject &obj) noexcept
void unread_implementation_objects(dunedaq::conffwk::ObjectState state) noexcept
Unread implementation objects (i.e. clear their cache).
ConfigObject * get_obj_pybind(const std::string &class_name, const std::string &id)
void export_schema(boost::property_tree::ptree &tree, const std::string &classes="", bool direct_only=false)
Export configuration schema into ptree.
void unsubscribe(CallbackId cb_handler=0)
Remove callback function.
void print_profiling_info() noexcept
Print out profiling information.
std::vector< dunedaq::conffwk::Version > get_versions(const std::string &since, const std::string &until, dunedaq::conffwk::Version::QueryType type=dunedaq::conffwk::Version::query_by_date, bool skip_irrelevant=true)
Get repository versions in interval.
std::atomic< uint_least64_t > p_number_of_template_object_read
void abort()
Abort database changes.
void unload()
Unload database.
bool test_object(const std::string &class_name, const std::string &id, unsigned long rlevel=0, const std::vector< std::string > *rclasses=0)
Test the object existence.
void add_include(const std::string &db_name, const std::string &include)
Add include file to existing database.
std::atomic< uint_least64_t > p_number_of_cache_hits
ConfigObject * create_and_return_obj_pybind(const std::string &at, const std::string &class_name, const std::string &id)
CallbackId subscribe(const ConfigurationSubscriptionCriteria &criteria, notify user_cb, void *user_param=nullptr)
Subscribe on configuration changes.
bool try_cast(const std::string &target, const std::string &source) noexcept
Checks if cast from source class to target class is allowed.
void rename_object(ConfigObject &obj, const std::string &new_id)
Cache of template object of given type.
The base class for any generated DAL object.
DalObject * get(ConfigObject &obj, bool upcast_unregistered=false)
Generic configuration exception.
Base class for any user define issue.
#define TLOG_DEBUG(lvl,...)
std::ostream & operator<<(std::ostream &, const ConfigurationChange &)
ERS_DEFINE_ISSUE_BASE_CXX(conffwk, Generic, conffwk::Exception, what,,((const char *) what)) ERS_DEFINE_ISSUE_BASE_CXX(conffwk
static void init_regex(std::unique_ptr< std::regex > &ptr, const std::string &str, const char *what)
static bool check_prefetch_needs()
static type<< " \""<< data<< "\" is not found",,((const char *) type)((const char *) data)) ERS_DEFINE_ISSUE_BASE_CXX(conffwk, DeletedObject, conffwk::Exception, "object \'"<< object_id<< '@'<< class_name<< "\' was deleted",,((const char *) class_name)((const char *) object_id)) namespace conffwk {template< typename T > T * get_new(ConfigObject &co, const std::string &attrname)
static void add_data(boost::property_tree::ptree &pt, const ConfigObject &obj, const dunedaq::conffwk::attribute_t &attribute, const std::string &empty_array_item)
static void add_array_item(boost::property_tree::ptree &pt, const T &val)
static void print_svect(std::ostream &s, const std::vector< std::string > &v, const char *name)
CIB Buffer std::string descriptor Message from std::string descriptor CIB process error
void error(const Issue &issue)
static const char * type(type_t type)
static const char * format2str(int_format_t format)
cardinality_t p_cardinality
static const char * card2str(cardinality_t cardinality)