12#include <unordered_map>
38 type <<
" \"" << data <<
"\" is not found",
40 ((const
char*)
type)((const
char*)data))
45 "object \'" << object_id <<
'@' << class_name <<
"\' was deleted",
47 ((const
char*)class_name)((const
char*)object_id))
53get_new(ConfigObject& co,
const std::string& attrname)
56 co.get(attrname, *retval);
87 return (getenv(
"TDAQ_DB_PREFETCH_ALL_DATA") !=
nullptr);
93 : p_number_of_cache_hits(0)
94 , p_number_of_template_object_created(0)
95 , p_number_of_template_object_read(0)
113 if (const char* env = getenv(
"TDAQ_DB"))
120 throw dunedaq::conffwk::Generic(
122 "no database parameter found (check parameter of the constructor or value of TDAQ_DB environment variable)");
124 std::string::size_type idx =
m_impl_spec.find_first_of(
':');
126 if (idx == std::string::npos) {
133 std::string plugin_name = std::string(
"lib") +
m_impl_name +
".so";
134 std::string impl_creator = std::string(
"_") +
m_impl_name +
"_creator_";
137 m_shlib_h = dlopen(plugin_name.c_str(), RTLD_LAZY | RTLD_GLOBAL);
140 std::ostringstream text;
141 text <<
"failed to load implementation plug-in \'" << plugin_name <<
"\': \"" << dlerror() <<
'\"';
142 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str()));
153 if ((
error = dlerror()) != 0) {
154 std::ostringstream text;
155 text <<
"failed to find implementation creator function \'" << impl_creator <<
"\' in plug-in \'" << plugin_name
156 <<
"\': \"" <<
error <<
'\"';
157 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str()));
174 TLOG_DEBUG(2) <<
"\n*** DUMP CONFIGURATION ***\n" << *
this;
182 std::cout <<
"Configuration profiler report:\n"
183 " number of created template objects: "
186 " number of read template objects: "
189 " number of cache hits: "
215 if (::getenv(
"TDAQ_DUMP_CONFFWK_PROFILER_INFO"))
229 }
catch (dunedaq::conffwk::Generic& ex) {
236 const std::string&
id,
238 unsigned long rlevel,
239 const std::vector<std::string>* rclasses)
242 _get(class_name,
id,
object, rlevel, rclasses);
247 const std::string& name,
249 unsigned long rlevel,
250 const std::vector<std::string>* rclasses)
253 m_impl->
get(class_name, name,
object, rlevel, rclasses);
254 }
catch (dunedaq::conffwk::Generic& ex) {
255 std::ostringstream text;
256 text <<
"failed to get object \'" << name <<
'@' << class_name <<
'\'';
257 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
263 std::vector<ConfigObject>& objects,
264 const std::string& query,
265 unsigned long rlevel,
266 const std::vector<std::string>* rclasses)
270 m_impl->
get(class_name, objects, query, rlevel, rclasses);
271 }
catch (dunedaq::conffwk::Generic& ex) {
272 std::ostringstream text;
273 text <<
"failed to get objects of class \'" << class_name <<
'\'';
274 if (!query.empty()) {
275 text <<
" with query \'" << query <<
'\'';
277 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
283 const std::string& query,
284 std::vector<ConfigObject>& objects,
285 unsigned long rlevel,
286 const std::vector<std::string>* rclasses)
290 m_impl->
get(obj_from, query, objects, rlevel, rclasses);
291 }
catch (dunedaq::conffwk::Generic& ex) {
292 std::ostringstream text;
293 text <<
"failed to get path \'" << query <<
"\' from object \'" << obj_from <<
'\'';
294 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
309 if (db_name.empty()) {
313 const char* s = ::getenv(
"TDAQ_DB_NAME");
314 if (s == 0 || *s == 0)
315 s = ::getenv(
"TDAQ_DB_DATA");
320 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"no database name was provided"));
348 TLOG_DEBUG(2) <<
"\n*** DUMP CONFIGURATION ***\n" << *
this;
350 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
358 throw dunedaq::conffwk::Generic(
ERS_HERE,
"nothing to unload");
393 for (
auto& a : *l.second)
420 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
427 }
catch (dunedaq::conffwk::Generic& ex) {
428 std::ostringstream text;
429 text <<
"failed to create database \'" << db_name <<
'\'';
430 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex));
438 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded"));
444 }
catch (dunedaq::conffwk::Generic& ex) {
445 std::ostringstream text;
446 text <<
"failed to get write access status for database \'" << db_name <<
'\'';
447 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex));
455 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
464 }
catch (dunedaq::conffwk::Generic& ex) {
465 std::ostringstream text;
466 text <<
"failed to add include \'" <<
include <<
"\' to database \'" << db_name <<
'\'';
467 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex));
475 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
485 }
catch (dunedaq::conffwk::Generic& ex) {
486 std::ostringstream text;
487 text <<
"failed to remove include \'" <<
include <<
"\' from database \'" << db_name <<
'\'';
488 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex));
496 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
502 }
catch (dunedaq::conffwk::Generic& ex) {
503 std::ostringstream text;
504 text <<
"failed to get includes of database \'" << db_name <<
'\'';
505 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex));
513 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
519 }
catch (dunedaq::conffwk::Generic& ex) {
520 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"get_updated_dbs failed", ex));
528 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
534 }
catch (dunedaq::conffwk::Generic& ex) {
535 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"set_commit_credentials failed", ex));
545 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
552 }
catch (dunedaq::conffwk::Generic& ex) {
553 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"commit failed", ex));
563 throw dunedaq::conffwk::Generic(
ERS_HERE,
"no implementation loaded");
576 }
catch (dunedaq::conffwk::Generic& ex) {
577 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"abort failed", ex));
589 }
catch (dunedaq::conffwk::Generic& ex) {
590 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"prefetch all data failed", ex));
597 if (unread_implementation_objs)
613 for (
auto& i :
m_impl->m_impl_objects)
614 for (
auto& j : *i.second) {
615 std::lock_guard<std::mutex> scoped_lock(j.second->m_mutex);
617 j.second->m_state = state;
620 for (
auto& x :
m_impl->m_tangled_objects) {
621 std::lock_guard<std::mutex> scoped_lock(x->m_mutex);
633 for (
const auto& j : i.second)
646std::deque<std::set<std::string>>
649 std::deque<std::set<std::string>> domains;
651 std::deque<dunedaq::conffwk::class_t> seeds;
654 if (ci.p_superclasses.empty())
658 for (
const auto& ci : seeds) {
660 std::set<std::string> class_domain;
661 class_domain.insert(ci.p_name);
662 class_domain.insert(ci.p_subclasses.begin(), ci.p_subclasses.end());
665 std::deque<std::set<std::string>> overlapping;
666 for (
auto& d : domains) {
667 std::set<std::string> intersection;
668 std::set_intersection(d.begin(),
670 class_domain.begin(),
672 std::inserter(intersection, intersection.begin()));
674 if (intersection.size() > 0) {
675 overlapping.push_back(d);
681 if (!overlapping.empty()) {
682 for (
auto& d : overlapping) {
684 class_domain.insert(d.begin(), d.end());
686 auto it = std::find(domains.begin(), domains.end(), d);
687 if (it != domains.end()) {
693 domains.push_back(class_domain);
706 for (
size_t i(0); i < domains.size(); ++i) {
707 const auto& dom = domains[i];
708 for (
const auto& class_name : dom) {
709 p_class_domain_map[&conffwk::DalFactory::instance().get_known_class_name_ref(class_name)] = i;
724 const std::string&
id,
725 unsigned long rlevel,
726 const std::vector<std::string>* rclasses)
731 }
catch (dunedaq::conffwk::Generic& ex) {
732 std::ostringstream text;
733 text <<
"failed to test existence of object \'" <<
id <<
'@' << class_name <<
'\'';
734 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
744 }
catch (dunedaq::conffwk::Generic& ex) {
745 std::ostringstream text;
746 text <<
"failed to create object \'" <<
id <<
'@' << class_name <<
'\'';
747 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
753 const std::string& class_name,
754 const std::string&
id,
760 }
catch (dunedaq::conffwk::Generic& ex) {
761 std::ostringstream text;
762 text <<
"failed to create object \'" <<
id <<
'@' << class_name <<
'\'';
763 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
774 }
catch (dunedaq::conffwk::Generic& ex) {
775 std::ostringstream text;
776 text <<
"failed to destroy object \'" <<
object <<
'\'';
777 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
784 std::lock_guard<std::mutex> scoped_impl_lock(
m_tmpl_mutex);
785 std::lock_guard<std::mutex> scoped_tmpl_lock(
m_impl_mutex);
787 std::lock_guard<std::mutex> scoped_obj_lock(
obj.m_impl->m_mutex);
789 const std::string old_id(
obj.m_impl->m_id);
791 obj.m_impl->throw_if_deleted();
792 obj.m_impl->rename(new_id);
793 obj.m_impl->m_id = new_id;
796 TLOG_DEBUG(3) <<
" * call rename \'" << old_id <<
"\' to \'" << new_id <<
"\' in class \'" <<
obj.class_name()
839 if (i != d_cache.end())
844 d_cache[class_name] = d;
848 catch (dunedaq::conffwk::Generic& ex) {
849 std::ostringstream text;
850 text <<
"failed to get description of class \'" << class_name <<
'\'';
851 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str(), ex);
858init_regex(std::unique_ptr<std::regex>& ptr,
const std::string& str,
const char* what)
862 ptr = std::make_unique<std::regex>(str);
863 }
catch (
const std::regex_error& ex) {
864 std::ostringstream text;
865 text <<
"failed to create " << what <<
" regex \"" << str <<
"\": " << ex.what();
866 throw dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str());
874 boost::property_tree::ptree child;
876 pt.push_back(std::make_pair(
"", child));
882 std::unique_ptr<std::regex> classes_regex;
884 init_regex(classes_regex, classes_str,
"classes");
886 auto cmp_str_ptr = [](
const std::string* s1,
const std::string* s2) {
return *s1 < *s2; };
887 std::set<
const std::string*,
decltype(cmp_str_ptr)> sorted_classes(cmp_str_ptr);
890 if (classes_str.empty() || std::regex_match(*c.first, *classes_regex.get()))
891 sorted_classes.insert(c.first);
893 for (
const auto& c : sorted_classes)
894 if (classes_str.empty() || std::regex_match(*c, *classes_regex.get())) {
897 boost::property_tree::ptree class_pt;
899 class_pt.put(
"abstract", info.p_abstract);
900 if (!info.p_description.empty())
901 class_pt.put(
"description", info.p_description);
903 if (!info.p_superclasses.empty()) {
906 for (
const auto& x : info.p_superclasses)
912 if (!info.p_attributes.empty()) {
913 boost::property_tree::ptree attributes;
915 for (
const auto& x : info.p_attributes) {
916 boost::property_tree::ptree attribute;
919 if (!x.p_range.empty())
920 attribute.put(
"range", x.p_range);
924 attribute.put(
"is-not-null", x.p_is_not_null);
925 if (x.p_is_multi_value)
926 attribute.put(
"is-multi-value", x.p_is_multi_value);
927 if (!x.p_default_value.empty())
928 attribute.put(
"default-value", x.p_default_value);
929 if (!x.p_description.empty())
930 attribute.put(
"description", x.p_description);
932 attributes.push_back(boost::property_tree::ptree::value_type(x.p_name, attribute));
935 class_pt.add_child(
"attributes", attributes);
938 if (!info.p_relationships.empty()) {
939 boost::property_tree::ptree relationships;
941 for (
const auto& x : info.p_relationships) {
942 boost::property_tree::ptree relationship;
944 relationship.put(
"type", x.p_type);
946 if (!x.p_is_aggregation)
947 relationship.put(
"is-aggregation", x.p_is_aggregation);
948 if (!x.p_description.empty())
949 relationship.put(
"description", x.p_description);
951 relationships.push_back(boost::property_tree::ptree::value_type(x.p_name, relationship));
954 class_pt.add_child(
"relationships", relationships);
957 pt.put_child(boost::property_tree::ptree::path_type(*c), class_pt);
964 const ConfigObject&
obj,
966 const std::string& empty_array_item)
968 auto& o =
const_cast<ConfigObject&
>(
obj);
969 if (!attribute.p_is_multi_value) {
971 const_cast<ConfigObject&
>(
obj).get(attribute.p_name, val);
972 pt.put(attribute.p_name, val);
974 std::vector<T> values;
975 o.get(attribute.p_name, values);
977 boost::property_tree::ptree children;
980 for (
const auto&
v : values)
983 else if (!empty_array_item.empty())
986 pt.add_child(attribute.p_name, children);
992 const ConfigObject&
obj,
994 const std::string& empty_array_item)
998 std::vector<ConfigObject> values;
999 const_cast<ConfigObject&
>(
obj).get(relationship.
p_name, values);
1001 boost::property_tree::ptree children;
1003 if (!values.empty())
1004 for (
const auto&
v : values)
1007 else if (!empty_array_item.empty())
1010 pt.add_child(relationship.
p_name, children);
1013 const_cast<ConfigObject&
>(
obj).get(relationship.
p_name, val);
1014 pt.put(relationship.
p_name, !val.is_null() ? val.full_name() :
"");
1020 const std::string& classes_str,
1021 const std::string& objects_str,
1022 const std::string& files_str,
1023 const std::string& empty_array_item)
1025 std::unique_ptr<std::regex> classes_regex, objects_regex, files_regex;
1027 init_regex(classes_regex, classes_str,
"classes");
1028 init_regex(objects_regex, objects_str,
"objects");
1031 auto cmp_str_ptr = [](
const std::string* s1,
const std::string* s2) {
return *s1 < *s2; };
1032 std::set<
const std::string*,
decltype(cmp_str_ptr)> sorted_classes(cmp_str_ptr);
1035 if (classes_str.empty() || std::regex_match(*c.first, *classes_regex.get()))
1036 sorted_classes.insert(c.first);
1038 for (
const auto& c : sorted_classes)
1039 if (classes_str.empty() || std::regex_match(*c, *classes_regex.get())) {
1042 boost::property_tree::ptree pt_objects;
1044 std::vector<ConfigObject> objects;
1048 std::set<
const ConfigObject*,
decltype(comp_obj_ptr)> sorted_objects(comp_obj_ptr);
1050 for (
const auto& x : objects)
1051 if (objects_str.empty() || std::regex_match(x.UID(), *objects_regex.get()))
1052 if (x.class_name() == *c)
1053 if (files_str.empty() || std::regex_match(x.contained_in(), *files_regex.get()))
1054 sorted_objects.insert(&x);
1056 if (!sorted_objects.empty()) {
1057 boost::property_tree::ptree pt_objects;
1059 for (
const auto& x : sorted_objects) {
1060 boost::property_tree::ptree data;
1062 for (
const auto& a : info.p_attributes)
1105 throw std::runtime_error(
"Invalid type of attribute " + a.p_name);
1108 for (
const auto& r : info.p_relationships)
1109 add_data(data, *x, r, empty_array_item);
1111 pt_objects.push_back(boost::property_tree::ptree::value_type(x->UID(), data));
1114 pt.put_child(boost::property_tree::ptree::path_type(*c), pt_objects);
1127std::vector<dunedaq::conffwk::Version>
1133 }
catch (dunedaq::conffwk::Generic& ex) {
1134 throw dunedaq::conffwk::Generic(
ERS_HERE,
"failed to get new versions", ex);
1138std::vector<dunedaq::conffwk::Version>
1140 const std::string& until,
1142 bool skip_irrelevant)
1147 }
catch (dunedaq::conffwk::Generic& ex) {
1148 throw dunedaq::conffwk::Generic(
ERS_HERE,
"failed to get versions", ex);
1174 throw dunedaq::conffwk::Generic(
ERS_HERE,
"callback function is not defined");
1179 Configuration::CallbackSubscription* cs =
new CallbackSubscription();
1181 cs->m_criteria = criteria;
1183 cs->m_param = parameter;
1193 }
catch (dunedaq::conffwk::Generic& ex) {
1196 throw dunedaq::conffwk::Generic(
ERS_HERE,
"subscription failed", ex);
1206 throw(dunedaq::conffwk::Generic(
ERS_HERE,
"callback function is not defined"));
1213 cs->m_param = parameter;
1239 std::ostringstream text;
1240 text <<
"unsubscription failed for CallbackId = " << (
void*)
id <<
" (no such callback id found)";
1241 throw(dunedaq::conffwk::Generic(
ERS_HERE, text.str().c_str()));
1256 }
catch (dunedaq::conffwk::Generic& ex) {
1257 throw dunedaq::conffwk::Generic(
ERS_HERE,
"unsubscription failed", ex);
1275 std::set<std::string> class_subscriptions;
1279 bool found_subscribe_all =
false;
1282 if (i->m_criteria.get_classes_subscription().empty() && i->m_criteria.get_objects_subscription().empty()) {
1283 found_subscribe_all =
true;
1287 if (found_subscribe_all ==
false) {
1290 for (
const auto& j : i->m_criteria.get_classes_subscription())
1291 class_subscriptions.insert(j);
1295 for (
const auto& j : i->m_criteria.get_objects_subscription()) {
1296 const std::string& obj_class_name = j.first;
1297 if (class_subscriptions.find(obj_class_name) == class_subscriptions.end())
1298 for (
const auto& k : j.second)
1299 obj_subscriptions[obj_class_name].insert(k);
1309 const std::string* class_name)
1314 if (i != cache.end()) {
1317 if (j != i->second->end()) {
1318 TLOG_DEBUG(2) <<
"set implementation object " << x <<
'@' << *class_name <<
" [" << (
void*)j->second
1321 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1332 if (i != cache.end()) {
1335 if (j != i->second->end()) {
1336 TLOG_DEBUG(2) <<
"re-set created implementation object " << x <<
'@' << *class_name <<
" ["
1337 << (
void*)j->second <<
']';
1339 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1349 if (i != cache.end()) {
1352 if (j != i->second->end()) {
1353 TLOG_DEBUG(2) <<
"clear implementation object " << x <<
'@' << *class_name <<
" [" << (
void*)j->second <<
']';
1355 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1372 TLOG_DEBUG(3) <<
"*** Enter Configuration::update_cache() with changes:\n" << changes;
1375 for (
const auto& i : changes) {
1376 const std::string* class_name = &DalFactory::instance().get_known_class_name_ref(i->get_class_name());
1384 for (
const auto& c : sc->second)
1391 for (
const auto& c : sc->second)
1395 for (
const auto& i : changes) {
1397 m_registry.update(i->get_class_name(), i->get_modified_objs(), i->get_removed_objs(), i->get_created_objs());
1460 TLOG_DEBUG(3) <<
"*** Enter Configuration::system_cb()\n"
1461 "*** Number of user subscriptions: "
1462 << conf->m_callbacks.size();
1466 std::lock_guard<std::mutex> scoped_lock(conf->m_impl_mutex);
1467 std::lock_guard<std::mutex> scoped_lock2(conf->m_actn_mutex);
1468 for (
auto& i : conf->m_actions)
1474 std::lock_guard<std::mutex> scoped_lock(conf->m_tmpl_mutex);
1475 std::lock_guard<std::mutex> scoped_lock2(conf->m_impl_mutex);
1476 conf->update_cache(changes);
1480 if (conf->m_callbacks.empty())
1486 std::lock_guard<std::mutex> scoped_lock(conf->m_else_mutex);
1489 if (conf->m_callbacks.size() == 1) {
1490 auto j = *conf->m_callbacks.begin();
1491 (*(j->m_cb))(changes, j->m_param);
1495 for (
const auto& j : conf->m_callbacks) {
1498 std::ostringstream text;
1500 text <<
"*** Process subscription " << (
void*)j
1502 " class subscription done for "
1503 << j->m_criteria.get_classes_subscription().size() <<
" classes:\n";
1505 for (
const auto& i1 : j->m_criteria.get_classes_subscription())
1506 text <<
" * class \"" << i1 <<
"\"\n";
1508 text <<
" object subscription done in " << j->m_criteria.get_objects_subscription().size() <<
" classes:\n";
1510 for (
const auto& i2 : j->m_criteria.get_objects_subscription()) {
1511 text <<
" * class \"" << (i2.first) <<
"\":\n";
1512 for (
const auto& i3 : i2.second)
1513 text <<
" - \"" << i3 <<
"\"\n";
1519 if (j->m_criteria.get_classes_subscription().empty() && j->m_criteria.get_objects_subscription().empty()) {
1521 TLOG_DEBUG(3) <<
"*** Invoke callback " << (
void*)j <<
" with\n" << changes;
1522 (*(j->m_cb))(changes, j->m_param);
1524 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown ers exception", ex));
1525 }
catch (
const std::exception& ex) {
1526 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown std exception", ex));
1528 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown unknown exception"));
1531 std::vector<ConfigurationChange*> changes1;
1533 for (
const auto& i : changes) {
1534 const std::string& cname = i->get_class_name();
1537 ConfigurationSubscriptionCriteria::ObjectMap::const_iterator p =
1538 j->m_criteria.get_objects_subscription().find(cname);
1539 const bool found_obj_subscription(p != j->m_criteria.get_objects_subscription().end());
1540 const bool found_class_subscription(j->m_criteria.get_classes_subscription().find(cname) !=
1541 j->m_criteria.get_classes_subscription().end());
1543 if (found_class_subscription || found_obj_subscription)
1546 if (found_class_subscription) {
1547 for (
const auto& k : i->m_modified)
1550 for (
const auto& k : i->m_created)
1553 for (
const auto& k : i->m_removed)
1557 if (found_obj_subscription) {
1558 for (
const auto& obj_id : i->m_modified)
1559 if (p->second.find(obj_id) != p->second.end())
1562 for (
const auto& obj_id : i->m_removed)
1563 if (p->second.find(obj_id) != p->second.end())
1564 class_changes->
m_removed.push_back(obj_id);
1569 if (class_changes) {
1572 delete class_changes;
1574 changes1.push_back(class_changes);
1578 if (!changes1.empty()) {
1579 TLOG_DEBUG(3) <<
"*** Invoke callback " << (
void*)j <<
" with\n" << changes1;
1582 (*(j->m_cb))(changes1, j->m_param);
1584 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown ers exception", ex));
1585 }
catch (
const std::exception& ex) {
1586 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown std exception", ex));
1588 ers::error(dunedaq::conffwk::Generic(
ERS_HERE,
"user callback thrown unknown exception"));
1591 for (
const auto& i : changes1)
1598 TLOG_DEBUG(3) <<
"*** Leave Configuration::system_cb()";
1604 TLOG_DEBUG(3) <<
"*** Enter Configuration::system_pre_cb()";
1606 std::lock_guard<std::mutex> scoped_lock(conf->m_else_mutex);
1608 for (
auto& j : conf->m_pre_callbacks) {
1609 TLOG_DEBUG(3) <<
"*** Invoke callback " << (
void*)(j);
1610 (*(j->m_cb))(j->m_param);
1613 TLOG_DEBUG(3) <<
"*** Leave Configuration::system_pre_cb()";
1618 const std::string& class_name,
1619 const std::string& obj_name,
1624 for (
const auto& c : changes)
1625 if (class_name == c->get_class_name()) {
1630 if (!class_changes) {
1632 changes.push_back(class_changes);
1635 std::vector<std::string>& clist = (action ==
'+' ? class_changes->
m_created
1636 : action ==
'-' ? class_changes->
m_removed
1639 clist.push_back(obj_name);
1645 for (
const auto& i : changes)
1652print_svect(std::ostream& s,
const std::vector<std::string>&
v,
const char* name)
1654 s <<
" * " <<
v.size() << name;
1656 for (
auto i =
v.begin(); i !=
v.end(); ++i) {
1657 s << ((i ==
v.begin()) ?
": " :
", ");
1658 s <<
'\"' << *i <<
'\"';
1665operator<<(std::ostream& s,
const ConfigurationChange& c)
1667 s <<
" changes for class \'" << c.get_class_name() <<
"\' include:\n";
1669 print_svect(s, c.get_modified_objs(),
" modified object(s)");
1670 print_svect(s, c.get_created_objs(),
" created object(s)");
1671 print_svect(s, c.get_removed_objs(),
" removed object(s)");
1677operator<<(std::ostream& s,
const std::vector<ConfigurationChange*>&
v)
1679 s <<
"There are configuration changes in " <<
v.size() <<
" classes:\n";
1681 for (
const auto& i :
v)
1690 s <<
"Configuration object:\n Inheritance Hierarchy (class - all it's superclasses):\n";
1693 s <<
" * \'" << *i.first <<
"\' - ";
1694 if (i.second.empty())
1697 for (
auto j = i.second.begin(); j != i.second.end(); ++j) {
1698 if (j != i.second.begin())
1700 s <<
'\'' << **j <<
'\'';
1721 return is_superclass_of(&DalFactory::instance().get_known_class_name_ref(base_class),
1722 &DalFactory::instance().get_known_class_name_ref(child_class));
1728 if (base_class == child_class) {
1729 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is allowed (equal classes)";
1733 conffwk::fmap<conffwk::fset>::iterator i = p_superclasses.find(child_class);
1735 if (i == p_superclasses.end()) {
1736 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class
1737 <<
"\' is not possible (base class is not loaded)";
1741 if (i->second.find(base_class) != i->second.end()) {
1742 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is allowed (use inheritance)";
1746 TLOG_DEBUG(50) <<
"cast \'" << *child_class <<
"\' => \'" << *base_class <<
"\' is not allowed (class \'"
1747 << *child_class <<
"\' has no \'" << *base_class <<
"\' as a superclass)";
1753operator<<(std::ostream& s,
const Configuration& c)
1787 const std::string& cname,
1788 const std::string& rname,
1791 std::ostringstream text;
1792 text <<
"failed to get " << what <<
" of class \'" << cname <<
"\' via relationship \'" << rname <<
"\' of object \'"
1800 std::ostringstream text;
1801 text <<
"failed to get objects of class \'" << cname <<
"\' referencing object \'" <<
obj <<
"\' via relationship \'"
1826std::vector<const DalObject*>
1828 const std::string& relationship_name,
1829 bool check_composite_only,
1830 bool upcast_unregistered,
1832 unsigned long rlevel,
1833 const std::vector<std::string>* rclasses)
1836 std::vector<ConfigObject> objs;
1839 obj.p_obj.referenced_by(objs, relationship_name, check_composite_only, rlevel, rclasses);
1842 }
catch (dunedaq::conffwk::Generic& ex) {
1848std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
1852 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> all_attributes_properties;
1856 for (
const auto& ap : c.p_attributes) {
1857 std::unordered_map<std::string, std::string> attribute_properties;
1860 attribute_properties[
"range"] = ap.p_range.empty() ?
"None" : ap.p_range;
1862 attribute_properties[
"description"] = ap.p_description;
1864 attribute_properties[
"multivalue"] = ap.p_is_multi_value ?
"True" :
"False";
1866 attribute_properties[
"not-null"] = ap.p_is_not_null ?
"True" :
"False";
1868 attribute_properties[
"init-value"] = ap.p_default_value.empty() ?
"None" : ap.p_default_value;
1870 all_attributes_properties[ap.p_name] = attribute_properties;
1873 return all_attributes_properties;
1876std::vector<std::string>
1879 std::vector<std::string> classes;
1881 classes.push_back(*it.first);
1891 this->
create(at, class_name,
id, *co);
1897 const std::string& class_name,
1898 const std::string&
id)
1901 this->
create(at, class_name,
id, *co);
1909 this->
get(class_name,
id, *co);
1910 if (co->is_null()) {
1917std::vector<ConfigObject>*
1920 auto objs =
new std::vector<ConfigObject>;
1921 this->
get(class_name, *objs, query);
1925std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
1929 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> all_relationships_properties;
1933 for (
const auto& rp : c.p_relationships) {
1934 std::unordered_map<std::string, std::string> relationship_properties;
1936 relationship_properties[
"type"] = rp.p_type;
1937 relationship_properties[
"description"] = rp.p_description;
1938 relationship_properties[
"multivalue"] =
1942 relationship_properties[
"aggregation"] = rp.p_is_aggregation ?
"True" :
"False";
1943 relationship_properties[
"not-null"] =
1947 all_relationships_properties[rp.p_name] = relationship_properties;
1950 return all_relationships_properties;
1953std::list<std::string>*
1956 auto l =
new std::list<std::string>;
1961std::vector<std::string>
1966 return c.p_subclasses;
1969std::vector<std::string>
1974 return c.p_superclasses;
1981 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 bool test_object(const std::string &class_name, const std::string &id, unsigned long rlevel, const std::vector< std::string > *rclasses)=0
Test object existence (used by Python binding).
virtual void subscribe(const std::set< std::string > &class_names, const std::map< std::string, std::set< std::string > > &objs, notify cb, pre_notify pre_cb)=0
Subscribe on database changes.
virtual void set_commit_credentials(const std::string &user, const std::string &password)=0
Set commit credentials.
virtual void close_db()=0
Close database implementation.
virtual void get_superclasses(conffwk::fmap< conffwk::fset > &schema)=0
Get inheritance hierarchy.
virtual void abort()=0
Abort database changes.
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.
virtual void get_includes(const std::string &db_name, std::list< std::string > &includes) const =0
Get included files.
virtual void print_profiling_info() noexcept=0
Print implementation specific profiling information.
virtual void prefetch_all_data()=0
Prefetch all data into client cache.
virtual void get_updated_dbs(std::list< std::string > &dbs) const =0
Get uncommitted files.
virtual bool is_writable(const std::string &db_name)=0
Return write access status.
virtual std::vector< dunedaq::conffwk::Version > get_changes()=0
Get newly available versions.
virtual bool loaded() const noexcept=0
Check if a database is loaded.
void rename_impl_object(const std::string *class_name, const std::string &old_id, const std::string &new_id) noexcept
rename object in cache
virtual void destroy(ConfigObject &object)=0
Destroy object of class by id.
virtual void add_include(const std::string &db_name, const std::string &include)=0
Add include file.
virtual void commit(const std::string &log_message)=0
Commit database changes.
void print_cache_info() noexcept
Print profiling information about objects in cache.
virtual std::vector< dunedaq::conffwk::Version > get_versions(const std::string &since, const std::string &until, dunedaq::conffwk::Version::QueryType type, bool skip_irrelevant)=0
Get archived versions.
virtual void remove_include(const std::string &db_name, const std::string &include)=0
Remove include file.
void set(Configuration *db) noexcept
set configuration object
virtual void create(const std::string &db_name, const std::list< std::string > &includes)=0
Create database.
virtual void open_db(const std::string &db_name)=0
Open database implementation in accordance with given name.
virtual void unsubscribe()=0
Remove subscription on database changes.
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
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.
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
conffwk::map< dunedaq::conffwk::class_t * > p_all_classes_desc_cache
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
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::list< ConfigAction * > m_actions
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::map< std::list< AttributeConverterBase * > * > m_convert_map
conffwk::fmap< conffwk::fset > p_superclasses
std::vector< dunedaq::conffwk::Version > get_changes()
Get new conffwk versions.
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
conffwk::map< dunedaq::conffwk::class_t * > p_direct_classes_desc_cache
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)
void _rename_object(std::string class_name, std::string old_id, std::string new_id)
Rename object of given template class (multi-thread unsafe).
void clear()
Clear the content of the registy.
void unread_all()
Set the status of all objects in cache to unread.
void update_class_maps()
Update the internal class domains map.
Base class for all conffwk exceptions.
Generic configuration exception.
Base class for any user define issue.
#define TLOG_DEBUG(lvl,...)
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)
std::ostream & operator<<(std::ostream &s, const ConfigurationChange &c)
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)