DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
Configuration.cpp
Go to the documentation of this file.
1#include <stdlib.h>
2#include <iostream>
3#include <regex>
4#include <sstream>
5#include <unordered_map>
6
7#include <dlfcn.h>
8
9#include "ers/ers.hpp"
11
12#include "conffwk/Change.hpp"
13#include "conffwk/DalObject.hpp"
20#include "conffwk/Schema.hpp"
21
22namespace dunedaq {
23
24 ERS_DEFINE_ISSUE_CXX( conffwk, Exception, , )
25
27 conffwk,
28 Generic,
29 conffwk::Exception,
30 what,
31 ,
32 ((const char*)what)
33 )
34
36 conffwk,
38 conffwk::Exception,
39 type << " \"" << data << "\" is not found",
40 ,
41 ((const char*)type)
42 ((const char*)data)
43 )
44
46 conffwk,
48 conffwk::Exception,
49 "object \'" << object_id << '@' << class_name << "\' was deleted",
50 ,
51 ((const char*)class_name)
52 ((const char*)object_id)
53 )
54
55
56namespace conffwk {
57
58template <typename T> static T* get_new(ConfigObject& co,
59 const std::string& attrname) {
60 T* retval = new T;
61 co.get(attrname, *retval);
62 return retval;
63}
64
65void
66Configuration::add_action(ConfigAction * ac)
67{
68 std::lock_guard<std::mutex> scoped_lock(m_actn_mutex);
69 m_actions.push_back(ac);
70}
71
72void
73Configuration::remove_action(ConfigAction * ac)
74{
75 std::lock_guard<std::mutex> scoped_lock(m_actn_mutex);
76 m_actions.remove(ac);
77}
78
79void
80Configuration::action_on_update(const ConfigObject& obj, const std::string& name)
81{
82 std::lock_guard<std::mutex> scoped_lock(m_actn_mutex);
83 for (auto &i : m_actions)
84 i->update(obj, name);
85}
86
88
89static bool
91{
92 return (getenv("TDAQ_DB_PREFETCH_ALL_DATA") != nullptr);
93}
94
96
97Configuration::Configuration() :
98 p_number_of_cache_hits(0), p_number_of_template_object_created(0), p_number_of_template_object_read(0), m_impl(nullptr), m_shlib_h(nullptr), m_registry(*this){
99
100 }
101
102Configuration::Configuration(const std::string& spec) :
103 p_number_of_cache_hits(0), p_number_of_template_object_created(0), p_number_of_template_object_read(0), m_impl(nullptr), m_shlib_h(nullptr), m_registry(*this)
104{
105 std::string s;
106
107 if (spec.empty())
108 {
109 if (const char *env = getenv("TDAQ_DB"))
110 m_impl_spec = env;
111 }
112 else
113 {
114 m_impl_spec = spec;
115 }
116
117 if (m_impl_spec.empty())
118 throw dunedaq::conffwk::Generic(ERS_HERE, "no database parameter found (check parameter of the constructor or value of TDAQ_DB environment variable)");
119
120 std::string::size_type idx = m_impl_spec.find_first_of(':');
121
122 if (idx == std::string::npos)
123 {
125 }
126 else
127 {
128 m_impl_name = m_impl_spec.substr(0, idx);
129 m_impl_param = m_impl_spec.substr(idx + 1);
130 }
131
132 std::string plugin_name = std::string("lib") + m_impl_name + ".so";
133 std::string impl_creator = std::string("_") + m_impl_name + "_creator_";
134
135 // load plug-in
136 m_shlib_h = dlopen(plugin_name.c_str(), RTLD_LAZY | RTLD_GLOBAL);
137
138 if (!m_shlib_h)
139 {
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() ) );
143 }
144
145 // search in plug-in implementation creator function
146
148 (*f)(const std::string& spec);
149
151 (*)(const std::string&))dlsym(m_shlib_h, impl_creator.c_str());
152
153 char * error = 0;
154
155 if ((error = dlerror()) != 0)
156 {
157 std::ostringstream text;
158 text << "failed to find implementation creator function \'" << impl_creator << "\' in plug-in \'" << plugin_name << "\': \"" << error << '\"';
159 throw(dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str() ) );
160 }
161
162
163 // create implementation
164
165 m_impl = (*f)(m_impl_param);
166
167 if (m_impl)
168 {
169 // m_impl->get_superclasses(p_superclasses);
170 // set_subclasses();
172 m_impl->set(this);
173 }
174
177
178 TLOG_DEBUG(2) << "\n*** DUMP CONFIGURATION ***\n" << *this;
179}
180
181
182void
184{
185 std::lock_guard < std::mutex > scoped_lock(m_impl_mutex);
186
187 std::cout << "Configuration profiler report:\n"
188 " number of created template objects: " << p_number_of_template_object_created << "\n"
189 " number of read template objects: " << p_number_of_template_object_read << "\n"
190 " number of cache hits: " << p_number_of_cache_hits << std::endl;
191
192 // FIXME: re-implement for the dal registry
193 // const char * s = ::getenv("TDAQ_DUMP_CONFFWK_PROFILER_INFO");
194 // if (s && !strcmp(s, "DEBUG"))
195 // {
196 // std::cout << " Details of accessed objects:\n";
197
198 // for (auto & i : m_cache_map)
199 // {
200 // Cache<DalObject> *c = static_cast<Cache<DalObject>*>(i.second);
201 // std::cout << " *** " << c->m_cache.size() << " objects is class \'" << *i.first << "\' were accessed ***\n";
202 // for (auto & j : c->m_cache)
203 // std::cout << " - object \'" << j.first << '\'' << std::endl;
204 // }
205 // }
206
207 if (m_impl)
208 {
211 }
212}
213
215{
216 if (::getenv("TDAQ_DUMP_CONFFWK_PROFILER_INFO"))
218
219 try
220 {
221 unload();
222
223 if (m_shlib_h)
224 {
225 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
226
227 delete m_impl;
228 m_impl = 0;
229 //dlclose(m_shlib_h);
230 m_shlib_h = 0;
231 }
232 }
233 catch (dunedaq::conffwk::Generic& ex)
234 {
235 ers::error(ex);
236 }
237}
238
239void
240Configuration::get(const std::string& class_name, const std::string& id, ConfigObject& object, unsigned long rlevel, const std::vector<std::string> * rclasses)
241{
242 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
243 _get(class_name, id, object, rlevel, rclasses);
244}
245
246void
247Configuration::_get(const std::string& class_name, const std::string& name, ConfigObject& object, unsigned long rlevel, const std::vector<std::string> * rclasses)
248{
249 try
250 {
251 m_impl->get(class_name, name, object, rlevel, rclasses);
252 }
253 catch (dunedaq::conffwk::Generic& ex)
254 {
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 );
258 }
259}
260
261void
262Configuration::get(const std::string& class_name, std::vector<ConfigObject>& objects, const std::string& query, unsigned long rlevel, const std::vector<std::string> * rclasses)
263{
264 try
265 {
266 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
267 m_impl->get(class_name, objects, query, rlevel, rclasses);
268 }
269 catch (dunedaq::conffwk::Generic& ex)
270 {
271 std::ostringstream text;
272 text << "failed to get objects of class \'" << class_name << '\'';
273 if (!query.empty())
274 {
275 text << " with query \'" << query << '\'';
276 }
277 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
278 }
279}
280
281void
282Configuration::get(const ConfigObject& obj_from, const std::string& query, std::vector<ConfigObject>& objects, unsigned long rlevel, const std::vector<std::string> * rclasses)
283{
284 try
285 {
286 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
287 m_impl->get(obj_from, query, objects, rlevel, rclasses);
288 }
289 catch (dunedaq::conffwk::Generic& ex)
290 {
291 std::ostringstream text;
292 text << "failed to get path \'" << query << "\' from object \'" << obj_from << '\'';
293 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
294 }
295}
296
297bool
298Configuration::loaded() const noexcept
299{
300 return (m_impl != nullptr) ? m_impl->loaded() : false;
301}
302
303void
304Configuration::load(const std::string& db_name)
305{
306 std::string name;
307
308 if (db_name.empty())
309 {
310 if (!m_impl_spec.empty() && !m_impl_param.empty())
311 {
312 name = m_impl_param;
313 }
314 else
315 {
316 const char * s = ::getenv("TDAQ_DB_NAME");
317 if (s == 0 || *s == 0)
318 s = ::getenv("TDAQ_DB_DATA");
319
320 if (s && *s)
321 {
322 name = s;
323 }
324 else
325 {
326 throw(dunedaq::conffwk::Generic( ERS_HERE, "no database name was provided" ) );
327 }
328 }
329 }
330 else
331 {
332 name = db_name;
333 }
334
335 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
336
337 // call conffwk actions if any
338 {
339 std::lock_guard<std::mutex> scoped_lock(m_actn_mutex);
340 for (auto & i : m_actions)
341 {
342 i->load();
343 }
344 }
345
346 if (m_impl)
347 {
348 m_impl->open_db(name);
349 // m_impl->get_superclasses(p_superclasses);
350 // set_subclasses();
352 m_impl->set(this);
353
355 {
357 }
358
359 TLOG_DEBUG(2) << "\n*** DUMP CONFIGURATION ***\n" << *this;
360 }
361 else
362 {
363 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
364 }
365}
366
367void
369{
370 if (m_impl == nullptr)
371 throw dunedaq::conffwk::Generic( ERS_HERE, "nothing to unload" );
372
373 std::lock_guard<std::mutex> scoped_lock1(m_tmpl_mutex); // always lock template objects mutex first
374 std::lock_guard<std::mutex> scoped_lock2(m_impl_mutex);
375
376 // call conffwk actions if any
377 {
378 std::lock_guard<std::mutex> scoped_lock(m_actn_mutex);
379 for(auto & i : m_actions)
380 {
381 i->unload();
382 }
383 }
384
385 // for (auto& i : m_cache_map) {
386 // delete i.second;
387 // }
388
389 // m_cache_map.clear();
391
392 {
393 std::lock_guard<std::mutex> scoped_lock3(m_else_mutex);
394
395 for (auto& cb : m_callbacks)
396 delete cb;
397
398 for (auto& cb : m_pre_callbacks)
399 delete cb;
400
401 m_callbacks.clear();
402 m_pre_callbacks.clear();
403
405
406 for (auto& l : m_convert_map) {
407 for (auto& a : *l.second)
408 delete a;
409
410 delete l.second;
411 }
412
413 m_convert_map.clear();
414 }
415
416 p_superclasses.clear();
417
418 for(auto& j : p_direct_classes_desc_cache)
419 delete j.second;
420
421 for(auto& j : p_all_classes_desc_cache)
422 delete j.second;
423
426
427 m_impl->close_db();
428}
429
430void
431Configuration::create(const std::string& db_name, const std::list<std::string>& includes)
432{
433 if (m_impl == nullptr)
434 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
435
436 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
437
438 try
439 {
440 m_impl->create(db_name, includes);
442 }
443 catch(dunedaq::conffwk::Generic & ex)
444 {
445 std::ostringstream text;
446 text << "failed to create database \'" << db_name << '\'';
447 throw ( dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex ) );
448 }
449}
450
451
452bool
453Configuration::is_writable(const std::string& db_name) const
454{
455 if (m_impl == nullptr)
456 throw(dunedaq::conffwk::Generic(ERS_HERE, "no implementation loaded" ) );
457
458 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
459
460 try
461 {
462 return m_impl->is_writable(db_name);
463 }
464 catch(dunedaq::conffwk::Generic & ex)
465 {
466 std::ostringstream text;
467 text << "failed to get write access status for database \'" << db_name<< '\'';
468 throw ( dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex ) );
469 }
470}
471
472
473void
474Configuration::add_include(const std::string& db_name, const std::string& include)
475{
476 if (m_impl == nullptr)
477 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
478
479 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
480
481 try
482 {
483 m_impl->add_include(db_name, include);
484 // m_impl->get_superclasses(p_superclasses);
485 // set_subclasses();
487 }
488 catch(dunedaq::conffwk::Generic & ex)
489 {
490 std::ostringstream text;
491 text << "failed to add include \'" << include << "\' to database \'" << db_name<< '\'';
492 throw ( dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex ) );
493 }
494}
495
496void
497Configuration::remove_include(const std::string& db_name, const std::string& include)
498{
499 if (m_impl == nullptr)
500 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
501
502 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
503 std::lock_guard<std::mutex> scoped_lock2(m_tmpl_mutex);
504
505 try
506 {
507 m_impl->remove_include(db_name, include);
508 // m_impl->get_superclasses(p_superclasses);
509 // set_subclasses();
511 }
512 catch(dunedaq::conffwk::Generic & ex)
513 {
514 std::ostringstream text;
515 text << "failed to remove include \'" << include << "\' from database \'" << db_name<< '\'';
516 throw ( dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex ) );
517 }
518}
519
520void
521Configuration::get_includes(const std::string& db_name, std::list<std::string>& includes) const
522{
523 if (m_impl == nullptr)
524 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
525
526 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
527
528 try
529 {
530 m_impl->get_includes(db_name, includes);
531 }
532 catch(dunedaq::conffwk::Generic & ex)
533 {
534 std::ostringstream text;
535 text << "failed to get includes of database \'" << db_name<< '\'';
536 throw ( dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex ) );
537 }
538}
539
540
541void
542Configuration::get_updated_dbs(std::list<std::string>& dbs) const
543{
544 if (m_impl == nullptr)
545 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
546
547 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
548
549 try
550 {
552 }
553 catch(dunedaq::conffwk::Generic & ex)
554 {
555 throw ( dunedaq::conffwk::Generic( ERS_HERE, "get_updated_dbs failed", ex ) );
556 }
557}
558
559
560void
561Configuration::set_commit_credentials(const std::string& user, const std::string& password)
562{
563 if (m_impl == nullptr)
564 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded" );
565
566 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
567
568 try
569 {
570 m_impl->set_commit_credentials(user, password);
571 }
572 catch(dunedaq::conffwk::Generic & ex)
573 {
574 throw ( dunedaq::conffwk::Generic( ERS_HERE, "set_commit_credentials failed", ex ) );
575 }
576}
577
578
579void
580Configuration::commit(const std::string& log_message)
581{
582 TLOG_DEBUG(1) << "call commit";
583
584 if (m_impl == nullptr)
585 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded");
586
587 std::lock_guard<std::mutex> scoped_lock1(m_tmpl_mutex); // always lock template objects mutex first
588 std::lock_guard<std::mutex> scoped_lock2(m_impl_mutex);
589
590 try
591 {
592 m_impl->commit(log_message);
593 }
594 catch (dunedaq::conffwk::Generic & ex)
595 {
596 throw(dunedaq::conffwk::Generic( ERS_HERE, "commit failed", ex ) );
597 }
598}
599
600void
602{
603 TLOG_DEBUG(1) << "call abort";
604
605 if (m_impl == nullptr)
606 throw dunedaq::conffwk::Generic( ERS_HERE, "no implementation loaded");
607
608 std::lock_guard<std::mutex> scoped_lock1(m_tmpl_mutex); // always lock template objects mutex first
609 std::lock_guard<std::mutex> scoped_lock2(m_impl_mutex);
610
611 try
612 {
613 m_impl->abort();
616 // m_impl->get_superclasses(p_superclasses);
617 // set_subclasses();
619
620 }
621 catch (dunedaq::conffwk::Generic & ex)
622 {
623 throw(dunedaq::conffwk::Generic( ERS_HERE, "abort failed", ex));
624 }
625}
626
627void
629{
630 std::lock_guard<std::mutex> scoped_lock1(m_tmpl_mutex); // always lock template objects mutex first
631 std::lock_guard<std::mutex> scoped_lock2(m_impl_mutex);
632
633 try
634 {
636 }
637 catch (dunedaq::conffwk::Generic & ex)
638 {
639 throw(dunedaq::conffwk::Generic( ERS_HERE, "prefetch all data failed", ex));
640 }
641}
642
643void
644Configuration::unread_all_objects(bool unread_implementation_objs) noexcept
645{
646 if (unread_implementation_objs)
647 unread_implementation_objects(dunedaq::conffwk::Unknown);
648
649 unread_template_objects();
650}
651
652
653// FIXME: find better name?
654void
659
660void
662{
663 for (auto &i : m_impl->m_impl_objects)
664 for (auto &j : *i.second)
665 {
666 std::lock_guard<std::mutex> scoped_lock(j.second->m_mutex);
667 j.second->clear();
668 j.second->m_state = state;
669 }
670
671 for (auto& x : m_impl->m_tangled_objects)
672 {
673 std::lock_guard<std::mutex> scoped_lock(x->m_mutex);
674 x->clear();
675 x->m_state = state;
676 }
677}
678
679
680void
682{
683 p_subclasses.clear();
684
685 for (const auto &i : p_superclasses)
686 for (const auto &j : i.second)
687 p_subclasses[j].insert(i.first);
688}
689
690
691void
699
700
701std::deque<std::set<std::string>>
703{
704 std::deque<std::set<std::string>> domains;
705
706 std::deque<dunedaq::conffwk::class_t> seeds;
707 for (const auto& c : get_class_list()) {
708 auto ci = this->_get_class_info(c);
709 if (ci.p_superclasses.empty())
710 seeds.push_back(ci);
711 }
712
713 for (const auto& ci : seeds) {
714 // Make a candidate domain based using the seed subclasses
715 std::set<std::string> class_domain;
716 class_domain.insert(ci.p_name);
717 class_domain.insert(ci.p_subclasses.begin(), ci.p_subclasses.end());
718
719 // Look for overlaps with other domains
720 std::deque<std::set<std::string>> overlapping;
721 for (auto& d : domains) {
722 std::set<std::string> intersection;
723 std::set_intersection(d.begin(), d.end(), class_domain.begin(), class_domain.end(), std::inserter(intersection, intersection.begin()));
724 // non-zero intersection, overlap found
725 if (intersection.size() > 0) {
726 overlapping.push_back(d);
727 }
728 }
729
730 // If overlapping are found, add all overlapping to
731 // the new domain and remove them from the domain list
732 if ( !overlapping.empty() ) {
733 for( auto& d : overlapping ) {
734 // merge the existing cluster in class_domain
735 class_domain.insert(d.begin(), d.end());
736 // Remove the old cluster from the list
737 auto it = std::find(domains.begin(), domains.end(), d);
738 if (it!= domains.end()) {
739 domains.erase(it);
740 }
741 }
742 }
743
744 domains.push_back(class_domain);
745 }
746
747 return domains;
748}
749
750
751void
753
754 p_class_domain_map.clear();
755
756 auto domains = this->find_class_domains();
757 for( size_t i(0); i<domains.size(); ++i ) {
758 const auto& dom = domains[i];
759 for( const auto& class_name : dom ) {
760 p_class_domain_map[&conffwk::DalFactory::instance().get_known_class_name_ref(class_name)] = i;
761 }
762 }
763}
764
765
767
768 //
769 // Test, create and destroy object methods
770 //
771
773
774bool
775Configuration::test_object(const std::string& class_name, const std::string& id, unsigned long rlevel, const std::vector<std::string> * rclasses)
776{
777 try
778 {
779 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
780 return m_impl->test_object(class_name, id, rlevel, rclasses);
781 }
782 catch (dunedaq::conffwk::Generic& ex)
783 {
784 std::ostringstream text;
785 text << "failed to test existence of object \'" << id << '@' << class_name << '\'';
786 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
787 }
788}
789
790void
791Configuration::create(const std::string& at, const std::string& class_name, const std::string& id, ConfigObject& object)
792{
793 try
794 {
795 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
796 m_impl->create(at, class_name, id, object);
797 }
798 catch (dunedaq::conffwk::Generic& ex)
799 {
800 std::ostringstream text;
801 text << "failed to create object \'" << id << '@' << class_name << '\'';
802 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
803 }
804}
805
806void
807Configuration::create(const ConfigObject& at, const std::string& class_name, const std::string& id, ConfigObject& object)
808{
809 try
810 {
811 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
812 m_impl->create(at, class_name, id, object);
813 }
814 catch (dunedaq::conffwk::Generic& ex)
815 {
816 std::ostringstream text;
817 text << "failed to create object \'" << id << '@' << class_name << '\'';
818 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
819 }
820}
821
822
823void
825{
826 try
827 {
828 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
829 std::lock_guard<std::mutex> scoped_lock2(m_tmpl_mutex);
830 m_impl->destroy(object);
831 }
832 catch (dunedaq::conffwk::Generic& ex)
833 {
834 std::ostringstream text;
835 text << "failed to destroy object \'" << object << '\'';
836 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
837 }
838}
839
840
841void
842Configuration::rename_object(ConfigObject& obj, const std::string& new_id)
843{
844 std::lock_guard<std::mutex> scoped_impl_lock(m_tmpl_mutex); // always lock template objects mutex first
845 std::lock_guard<std::mutex> scoped_tmpl_lock(m_impl_mutex);
846
847 std::lock_guard<std::mutex> scoped_obj_lock(obj.m_impl->m_mutex);
848
849 const std::string old_id(obj.m_impl->m_id);
850
851 obj.m_impl->throw_if_deleted();
852 obj.m_impl->rename(new_id);
853 obj.m_impl->m_id = new_id;
854 m_impl->rename_impl_object(obj.m_impl->m_class_name, old_id, new_id);
855
856 TLOG_DEBUG(3) << " * call rename \'" << old_id << "\' to \'" << new_id << "\' in class \'" << obj.class_name() << "\')";
857
858 m_registry._rename_object(obj.class_name(), old_id, new_id);
859
860 // conffwk::fmap<CacheBase*>::iterator j = m_cache_map.find(&obj.class_name());
861 // if (j != m_cache_map.end())
862 // j->second->m_functions.m_rename_object_fn(j->second, old_id, new_id);
863
864 // conffwk::fmap<conffwk::fset>::const_iterator sc = p_superclasses.find(&obj.class_name());
865
866 // if (sc != p_superclasses.end())
867 // for (conffwk::fset::const_iterator c = sc->second.begin(); c != sc->second.end(); ++c)
868 // {
869 // conffwk::fmap<CacheBase*>::iterator j = m_cache_map.find(*c);
870
871 // if (j != m_cache_map.end())
872 // j->second->m_functions.m_rename_object_fn(j->second, old_id, new_id);
873 // }
874}
875
876
877
879//
880// Meta-information access methods
881//
883
884
886Configuration::get_class_info(const std::string& class_name, bool direct_only)
887{
888 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
889
890 return this->_get_class_info(class_name, direct_only);
891}
892
893
895Configuration::_get_class_info(const std::string& class_name, bool direct_only)
896{
898
900
901 if (i != d_cache.end())
902 return *(i->second);
903
904 try
905 {
906 dunedaq::conffwk::class_t * d = m_impl->get(class_name, direct_only);
907 d_cache[class_name] = d;
908 return *d;
909 }
910 // catch Generic exception only; the NotFound is forwarded from implementation
911 catch (dunedaq::conffwk::Generic& ex)
912 {
913 std::ostringstream text;
914 text << "failed to get description of class \'" << class_name << '\'';
915 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str(), ex );
916 }
917}
918
920
921static void
922init_regex(std::unique_ptr<std::regex>& ptr, const std::string& str, const char * what)
923{
924 if (!str.empty())
925 try
926 {
927 ptr = std::make_unique<std::regex>(str);
928 }
929 catch (const std::regex_error &ex)
930 {
931 std::ostringstream text;
932 text << "failed to create " << what << " regex \"" << str << "\": " << ex.what();
933 throw dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str());
934 }
935}
936
937
938template<class T>
939static void
940add_array_item(boost::property_tree::ptree &pt, const T &val)
941{
942 boost::property_tree::ptree child;
943 child.put("", val);
944 pt.push_back(std::make_pair("", child));
945}
946
947void
948Configuration::export_schema(boost::property_tree::ptree& pt, const std::string& classes_str, bool direct_only)
949{
950 std::unique_ptr<std::regex> classes_regex;
951
952 init_regex(classes_regex, classes_str, "classes");
953
954 auto cmp_str_ptr = [](const std::string * s1, const std::string * s2) { return *s1 < *s2; };
955 std::set<const std::string *, decltype(cmp_str_ptr)> sorted_classes(cmp_str_ptr);
956
957 for (const auto &c : superclasses())
958 if (classes_str.empty() || std::regex_match(*c.first, *classes_regex.get()))
959 sorted_classes.insert(c.first);
960
961 for (const auto &c : sorted_classes)
962 if (classes_str.empty() || std::regex_match(*c, *classes_regex.get()))
963 {
964 const dunedaq::conffwk::class_t& info(get_class_info(*c, direct_only));
965
966 boost::property_tree::ptree class_pt;
967
968 class_pt.put("abstract", info.p_abstract);
969 if (!info.p_description.empty())
970 class_pt.put("description", info.p_description);
971
972 if (!info.p_superclasses.empty())
973 {
974 boost::property_tree::ptree superclasses;
975
976 for (const auto &x : info.p_superclasses)
978
979 class_pt.add_child("superclasses", superclasses);
980 }
981
982 if (!info.p_attributes.empty())
983 {
984 boost::property_tree::ptree attributes;
985
986 for (const auto &x : info.p_attributes)
987 {
988 boost::property_tree::ptree attribute;
989
990 attribute.put("type", dunedaq::conffwk::attribute_t::type(x.p_type));
991 if (!x.p_range.empty())
992 attribute.put("range", x.p_range);
993 if (x.p_int_format != dunedaq::conffwk::na_int_format)
994 attribute.put("format", dunedaq::conffwk::attribute_t::format2str(x.p_int_format));
995 if (x.p_is_not_null)
996 attribute.put("is-not-null", x.p_is_not_null);
997 if (x.p_is_multi_value)
998 attribute.put("is-multi-value", x.p_is_multi_value);
999 if (!x.p_default_value.empty())
1000 attribute.put("default-value", x.p_default_value);
1001 if (!x.p_description.empty())
1002 attribute.put("description", x.p_description);
1003
1004 attributes.push_back(boost::property_tree::ptree::value_type(x.p_name, attribute));
1005 }
1006
1007 class_pt.add_child("attributes", attributes);
1008 }
1009
1010 if (!info.p_relationships.empty())
1011 {
1012 boost::property_tree::ptree relationships;
1013
1014 for (const auto &x : info.p_relationships)
1015 {
1016 boost::property_tree::ptree relationship;
1017
1018 relationship.put("type", x.p_type);
1019 relationship.put("cardinality", dunedaq::conffwk::relationship_t::card2str(x.p_cardinality));
1020 if (!x.p_is_aggregation)
1021 relationship.put("is-aggregation", x.p_is_aggregation);
1022 if (!x.p_description.empty())
1023 relationship.put("description", x.p_description);
1024
1025 relationships.push_back(boost::property_tree::ptree::value_type(x.p_name, relationship));
1026 }
1027
1028 class_pt.add_child("relationships", relationships);
1029 }
1030
1031 pt.put_child(boost::property_tree::ptree::path_type(*c), class_pt);
1032 }
1033}
1034
1035template<class T>
1036static void
1037add_data(boost::property_tree::ptree &pt, const ConfigObject &obj, const dunedaq::conffwk::attribute_t &attribute, const std::string &empty_array_item)
1038{
1039 auto &o = const_cast<ConfigObject&>(obj);
1040 if (!attribute.p_is_multi_value)
1041 {
1042 T val;
1043 const_cast<ConfigObject&>(obj).get(attribute.p_name, val);
1044 pt.put(attribute.p_name, val);
1045 }
1046 else
1047 {
1048 std::vector<T> values;
1049 o.get(attribute.p_name, values);
1050
1051 boost::property_tree::ptree children;
1052
1053 if (!values.empty())
1054 for (const auto &v : values)
1055 add_array_item(children, v);
1056
1057 else if (!empty_array_item.empty())
1058 add_array_item(children, empty_array_item);
1059
1060 pt.add_child(attribute.p_name, children);
1061 }
1062}
1063
1064static void
1065add_data(boost::property_tree::ptree &pt, const ConfigObject &obj, const dunedaq::conffwk::relationship_t &relationship, const std::string &empty_array_item)
1066{
1068 {
1069 std::vector<ConfigObject> values;
1070 const_cast<ConfigObject&>(obj).get(relationship.p_name, values);
1071
1072 boost::property_tree::ptree children;
1073
1074 if (!values.empty())
1075 for (const auto &v : values)
1076 add_array_item(children, v.full_name());
1077
1078 else if (!empty_array_item.empty())
1079 add_array_item(children, empty_array_item);
1080
1081 pt.add_child(relationship.p_name, children);
1082 }
1083 else
1084 {
1085 ConfigObject val;
1086 const_cast<ConfigObject&>(obj).get(relationship.p_name, val);
1087 pt.put(relationship.p_name, !val.is_null() ? val.full_name() : "");
1088 }
1089}
1090
1091void
1092Configuration::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)
1093{
1094 std::unique_ptr<std::regex> classes_regex, objects_regex, files_regex;
1095
1096 init_regex(classes_regex, classes_str, "classes");
1097 init_regex(objects_regex, objects_str, "objects");
1098 init_regex(files_regex, files_str, "files");
1099
1100 auto cmp_str_ptr = [](const std::string * s1, const std::string * s2) { return *s1 < *s2; };
1101 std::set<const std::string *, decltype(cmp_str_ptr)> sorted_classes(cmp_str_ptr);
1102
1103 for (const auto &c : superclasses())
1104 if (classes_str.empty() || std::regex_match(*c.first, *classes_regex.get()))
1105 sorted_classes.insert(c.first);
1106
1107 for (const auto &c : sorted_classes)
1108 if (classes_str.empty() || std::regex_match(*c, *classes_regex.get()))
1109 {
1111
1112 boost::property_tree::ptree pt_objects;
1113
1114 std::vector<ConfigObject> objects;
1115 get(*c, objects);
1116
1117 auto comp_obj_ptr = [](const ConfigObject * o1, const ConfigObject * o2) { return o1->UID() < o2->UID(); };
1118 std::set<const ConfigObject *, decltype(comp_obj_ptr)> sorted_objects(comp_obj_ptr);
1119
1120 for (const auto& x : objects)
1121 if (objects_str.empty() || std::regex_match(x.UID(), *objects_regex.get()))
1122 if (x.class_name() == *c)
1123 if(files_str.empty() || std::regex_match(x.contained_in(), *files_regex.get()))
1124 sorted_objects.insert(&x);
1125
1126 if (!sorted_objects.empty())
1127 {
1128 boost::property_tree::ptree pt_objects;
1129
1130 for (const auto& x : sorted_objects)
1131 {
1132 boost::property_tree::ptree data;
1133
1134 for (const auto &a : info.p_attributes)
1135 switch (a.p_type)
1136 {
1138 add_data<bool>(data, *x, a, empty_array_item);
1139 break;
1141 add_data<int8_t>(data, *x, a, empty_array_item);
1142 break;
1144 add_data<uint8_t>(data, *x, a, empty_array_item);
1145 break;
1147 add_data<int16_t>(data, *x, a, empty_array_item);
1148 break;
1150 add_data<uint16_t>(data, *x, a, empty_array_item);
1151 break;
1153 add_data<int32_t>(data, *x, a, empty_array_item);
1154 break;
1156 add_data<uint32_t>(data, *x, a, empty_array_item);
1157 break;
1159 add_data<int64_t>(data, *x, a, empty_array_item);
1160 break;
1162 add_data<uint64_t>(data, *x, a, empty_array_item);
1163 break;
1165 add_data<float>(data, *x, a, empty_array_item);
1166 break;
1168 add_data<double>(data, *x, a, empty_array_item);
1169 break;
1175 add_data<std::string>(data, *x, a, empty_array_item);
1176 break;
1177 default:
1178 throw std::runtime_error("Invalid type of attribute " + a.p_name);
1179
1180 }
1181
1182 for (const auto &r : info.p_relationships)
1183 add_data(data, *x, r, empty_array_item);
1184
1185 pt_objects.push_back(boost::property_tree::ptree::value_type(x->UID(), data));
1186 }
1187
1188 pt.put_child(boost::property_tree::ptree::path_type(*c), pt_objects);
1189 }
1190 }
1191}
1192
1194
1195 //
1196 // Methods to get versions
1197 //
1198
1200
1201
1202std::vector<dunedaq::conffwk::Version>
1204{
1205 try
1206 {
1207 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
1208 return m_impl->get_changes();
1209 }
1210 catch (dunedaq::conffwk::Generic& ex)
1211 {
1212 throw dunedaq::conffwk::Generic( ERS_HERE, "failed to get new versions", ex );
1213 }
1214}
1215
1216
1217std::vector<dunedaq::conffwk::Version>
1218Configuration::get_versions(const std::string& since, const std::string& until, dunedaq::conffwk::Version::QueryType type, bool skip_irrelevant)
1219{
1220 try
1221 {
1222 std::lock_guard<std::mutex> scoped_lock(m_impl_mutex);
1223 return m_impl->get_versions(since, until, type, skip_irrelevant);
1224 }
1225 catch (dunedaq::conffwk::Generic& ex)
1226 {
1227 throw dunedaq::conffwk::Generic( ERS_HERE, "failed to get versions", ex );
1228 }
1229}
1230
1232
1233 //
1234 // Subscription and notification methods
1235 //
1236
1238
1239
1240 // The methods checks that given callback exists
1241
1244{
1245 return ((!cb_handler || (m_callbacks.find(cb_handler) == m_callbacks.end())) ? 0 : cb_handler);
1246}
1247
1248
1250Configuration::subscribe(const ConfigurationSubscriptionCriteria& criteria, notify user_cb, void * parameter)
1251{
1252 // check if there is no subscription function provided
1253
1254 if (!user_cb)
1255 {
1256 throw dunedaq::conffwk::Generic( ERS_HERE, "callback function is not defined" );
1257 }
1258
1259 // create callback subscription structure
1260
1261 Configuration::CallbackSubscription * cs = new CallbackSubscription();
1262
1263 cs->m_criteria = criteria;
1264 cs->m_cb = user_cb;
1265 cs->m_param = parameter;
1266
1267 // FIXME: bug in OksConfiguration subscribe() with enter_loop=true
1268 std::lock_guard<std::mutex> scoped_lock(m_else_mutex);// TEST 2010-02-03
1269
1270 m_callbacks.insert(cs);
1271
1272 try
1273 {
1275 return cs;
1276 }
1277 catch (dunedaq::conffwk::Generic& ex)
1278 {
1279 m_callbacks.erase(cs);
1280 delete cs;
1281 throw dunedaq::conffwk::Generic( ERS_HERE, "subscription failed", ex );
1282 }
1283}
1284
1286Configuration::subscribe(pre_notify user_cb, void * parameter)
1287{
1288 // check if there is no subscription function provided
1289
1290 if (!user_cb)
1291 throw(dunedaq::conffwk::Generic( ERS_HERE, "callback function is not defined" ) );
1292
1293 // create callback subscription structure
1294
1295 CallbackPreSubscription * cs = new CallbackPreSubscription();
1296
1297 cs->m_cb = user_cb;
1298 cs->m_param = parameter;
1299
1300 {
1301 std::lock_guard<std::mutex> scoped_lock(m_else_mutex);
1302 m_pre_callbacks.insert(cs);
1303 }
1304
1305 return reinterpret_cast<CallbackSubscription *>(cs);
1306}
1307
1308
1309void
1311{
1312 std::lock_guard < std::mutex > scoped_lock(m_else_mutex);
1313
1314 if (id)
1315 {
1316 CallbackSet::iterator i = m_callbacks.find(id);
1317 PreCallbackSet::iterator j = m_pre_callbacks.find(reinterpret_cast<CallbackPreSubscription *>(id));
1318
1319 if (i != m_callbacks.end())
1320 {
1321 delete id;
1322 m_callbacks.erase(i);
1323 }
1324 else if (j != m_pre_callbacks.end())
1325 {
1326 delete reinterpret_cast<CallbackPreSubscription *>(id);
1327 m_pre_callbacks.erase(j);
1328 }
1329 else
1330 {
1331 std::ostringstream text;
1332 text << "unsubscription failed for CallbackId = " << (void *) id << " (no such callback id found)";
1333 throw(dunedaq::conffwk::Generic( ERS_HERE, text.str().c_str() ) );
1334 }
1335 }
1336 else
1337 {
1338 for (auto &i : m_callbacks)
1339 delete i;
1340
1341 for (auto &i : m_pre_callbacks)
1342 delete i;
1343
1344 m_callbacks.clear();
1345 m_pre_callbacks.clear();
1346 }
1347
1348 try
1349 {
1351 }
1352 catch (dunedaq::conffwk::Generic& ex)
1353 {
1354 throw dunedaq::conffwk::Generic( ERS_HERE, "unsubscription failed", ex );
1355 }
1356}
1357
1358void
1360{
1361 // check that there is no at least one subscription
1362 // if NO, then unsubscribe
1363
1364 if (m_callbacks.empty())
1365 {
1367 return;
1368 }
1369
1370 // prepare subscription criteria
1371
1373 std::set<std::string> class_subscriptions;
1374
1375 // among existing subscriptions find one who has all subscriptions
1376
1377 bool found_subscribe_all = false;
1378
1379 for (const auto &i : m_callbacks)
1380 if (i->m_criteria.get_classes_subscription().empty() && i->m_criteria.get_objects_subscription().empty())
1381 {
1382 found_subscribe_all = true;
1383 break;
1384 }
1385
1386 if (found_subscribe_all == false)
1387 {
1388 // build list of all classes for which there is a subscription
1389 for (const auto &i : m_callbacks)
1390 for (const auto &j : i->m_criteria.get_classes_subscription())
1391 class_subscriptions.insert(j);
1392
1393 // build list of all objects for which there is a subscription (if there is no such class)
1394 for (const auto &i : m_callbacks)
1395 for (const auto &j : i->m_criteria.get_objects_subscription())
1396 {
1397 const std::string &obj_class_name = j.first;
1398 if (class_subscriptions.find(obj_class_name) == class_subscriptions.end())
1399 for (const auto &k : j.second)
1400 obj_subscriptions[obj_class_name].insert(k);
1401 }
1402 }
1403
1404 m_impl->subscribe(class_subscriptions, obj_subscriptions, system_cb, system_pre_cb);
1405}
1406
1407
1408void
1410{
1411 if (change.get_removed_objs().empty() == false)
1412 {
1413 conffwk::pmap<conffwk::map<ConfigObjectImpl *> *>::iterator i = cache.find(class_name);
1414
1415 if (i != cache.end())
1416 {
1417 for (auto & x : change.get_removed_objs())
1418 {
1419 conffwk::map<ConfigObjectImpl *>::iterator j = i->second->find(x);
1420 if (j != i->second->end())
1421 {
1422 TLOG_DEBUG( 2 ) << "set implementation object " << x << '@' << *class_name << " [" << (void *)j->second << "] deleted";
1423
1424 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1425 j->second->m_state = dunedaq::conffwk::Deleted;
1426 j->second->clear();
1427 }
1428 }
1429 }
1430 }
1431
1432 if (change.get_created_objs().empty() == false)
1433 {
1434 conffwk::pmap<conffwk::map<ConfigObjectImpl *> *>::iterator i = cache.find(class_name);
1435
1436 if (i != cache.end())
1437 {
1438 for (auto & x : change.get_created_objs())
1439 {
1440 conffwk::map<ConfigObjectImpl *>::iterator j = i->second->find(x);
1441 if (j != i->second->end())
1442 {
1443 TLOG_DEBUG( 2 ) << "re-set created implementation object " << x << '@' << *class_name << " [" << (void *)j->second << ']';
1444
1445 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1446 j->second->reset(); // it does not matter what the state was, always reset
1447 }
1448 }
1449 }
1450 }
1451
1452 if (change.get_modified_objs().empty() == false)
1453 {
1454 conffwk::pmap<conffwk::map<ConfigObjectImpl *> *>::iterator i = cache.find(class_name);
1455
1456 if (i != cache.end())
1457 {
1458 for (auto & x : change.get_modified_objs())
1459 {
1460 conffwk::map<ConfigObjectImpl *>::iterator j = i->second->find(x);
1461 if (j != i->second->end())
1462 {
1463 TLOG_DEBUG(2) << "clear implementation object " << x << '@' << *class_name << " [" << (void *)j->second << ']';
1464
1465 std::lock_guard<std::mutex> scoped_lock(j->second->m_mutex);
1466
1467 if(j->second->m_state != dunedaq::conffwk::Valid)
1468 j->second->reset();
1469 else
1470 j->second->clear();
1471 }
1472 }
1473 }
1474 }
1475}
1476
1477
1478 // note, the std::lock_guard<std::mutex> scoped_lock(conf->m_tmpl_mutex) is already set by caller
1479
1480void
1481Configuration::update_cache(std::vector<ConfigurationChange *>& changes) noexcept
1482{
1483 TLOG_DEBUG(3) << "*** Enter Configuration::update_cache() with changes:\n" << changes;
1484
1485 // Remove deleted and update modified implementation objects first
1486 for (const auto& i : changes)
1487 {
1488 const std::string * class_name = &DalFactory::instance().get_known_class_name_ref(i->get_class_name());
1489
1490 update_impl_objects(m_impl->m_impl_objects, *i, class_name);
1491
1492 // delete/update implementation objects defined in superclasses
1493 conffwk::fmap<conffwk::fset>::const_iterator sc = p_superclasses.find(class_name);
1494
1495 if (sc != p_superclasses.end())
1496 for (const auto &c : sc->second)
1497 update_impl_objects(m_impl->m_impl_objects, *i, c);
1498
1499 // delete/update implementation objects defined in subclasses
1500 sc = p_subclasses.find(class_name);
1501
1502 if (sc != p_subclasses.end())
1503 for (const auto &c : sc->second)
1504 update_impl_objects(m_impl->m_impl_objects, *i, c);
1505 }
1506
1507 for (const auto& i : changes)
1508 {
1509
1510 m_registry.update(i->get_class_name(), i->get_modified_objs(), i->get_removed_objs(), i->get_created_objs());
1511
1512 // const std::string * class_name = &DalFactory::instance().get_known_class_name_ref(i->get_class_name()); // FIXME: optimise with above
1513
1514 // // invoke configuration update if there are template objects of given class
1515
1516 // {
1517 // conffwk::fmap<CacheBase*>::iterator j = m_cache_map.find(class_name);
1518
1519 // if (j != m_cache_map.end())
1520 // {
1521 // TLOG_DEBUG(3) << " * call update on \'" << j->first << "\' template objects";
1522 // j->second->m_functions.m_update_fn(*this, i);
1523 // }
1524 // }
1525
1526
1527 // // invoke configuration update if there are template objects in super-classes
1528
1529 // {
1530 // conffwk::fmap<conffwk::fset>::const_iterator sc = p_superclasses.find(class_name);
1531
1532 // if (sc != p_superclasses.end())
1533 // {
1534 // for (const auto& c : sc->second)
1535 // {
1536 // conffwk::fmap<CacheBase*>::iterator j = m_cache_map.find(c);
1537
1538 // if (j != m_cache_map.end())
1539 // {
1540 // TLOG_DEBUG(3) << " * call update on \'" << j->first << "\' template objects (as super-class of \'" << *class_name << "\')";
1541 // j->second->m_functions.m_update_fn(*this, i);
1542 // }
1543 // }
1544 // }
1545 // }
1546
1547
1548 // // invoke configuration update if there are template objects in sub-classes
1549
1550 // {
1551 // conffwk::fmap<conffwk::fset>::const_iterator sc = p_subclasses.find(class_name);
1552
1553 // if (sc != p_subclasses.end())
1554 // {
1555 // for (const auto& c : sc->second)
1556 // {
1557 // conffwk::fmap<CacheBase*>::iterator j = m_cache_map.find(c);
1558
1559 // if (j != m_cache_map.end())
1560 // {
1561 // TLOG_DEBUG(3) << " * call update on \'" << j->first << "\' template objects (as sub-class of \'" << *class_name << "\')";
1562 // j->second->m_functions.m_update_fn(*this, i);
1563 // }
1564 // }
1565 // }
1566 // }
1567
1568 }
1569
1570}
1571
1572
1573void
1574Configuration::system_cb(std::vector<ConfigurationChange *>& changes, Configuration * conf) noexcept
1575{
1576
1577 TLOG_DEBUG(3) <<
1578 "*** Enter Configuration::system_cb()\n"
1579 "*** Number of user subscriptions: " << conf->m_callbacks.size()
1580 ;
1581
1582 // call conffwk actions if any
1583 {
1584 std::lock_guard<std::mutex> scoped_lock(conf->m_impl_mutex);
1585 std::lock_guard<std::mutex> scoped_lock2(conf->m_actn_mutex);
1586 for (auto & i : conf->m_actions)
1587 i->notify(changes);
1588 }
1589
1590
1591 // update template objects in cache
1592 {
1593 std::lock_guard<std::mutex> scoped_lock(conf->m_tmpl_mutex); // always lock template objects mutex first
1594 std::lock_guard<std::mutex> scoped_lock2(conf->m_impl_mutex);
1595 conf->update_cache(changes);
1596 }
1597
1598
1599 // user removed all subscriptions
1600 if(conf->m_callbacks.empty()) return;
1601
1602 // note, one cannot lock m_tmpl_mutex or m_impl_mutex here,
1603 // since user callback may call arbitrary get() methods to access conffwk
1604 // and template objects locking above two mutexes
1605 std::lock_guard<std::mutex> scoped_lock(conf->m_else_mutex);
1606
1607 // check if there is only one subscription
1608 if (conf->m_callbacks.size() == 1)
1609 {
1610 auto j = *conf->m_callbacks.begin();
1611 (*(j->m_cb))(changes, j->m_param);
1612 }
1613 // may need to calculate the changes for each subscription
1614 else
1615 {
1616 for (const auto &j : conf->m_callbacks)
1617 {
1618
1619 if (ers::debug_level() >= 3)
1620 {
1621 std::ostringstream text;
1622
1623 text <<
1624 "*** Process subscription " << (void*) j << "\n"
1625 " class subscription done for " << j->m_criteria.get_classes_subscription().size() << " classes:\n";
1626
1627 for (const auto &i1 : j->m_criteria.get_classes_subscription())
1628 text << " * class \"" << i1 << "\"\n";
1629
1630 text << " object subscription done in " << j->m_criteria.get_objects_subscription().size() << " classes:\n";
1631
1632 for (const auto &i2 : j->m_criteria.get_objects_subscription())
1633 {
1634 text << " * class \"" << (i2.first) << "\":\n";
1635 for (const auto &i3 : i2.second)
1636 text << " - \"" << i3 << "\"\n";
1637 }
1638
1639 TLOG_DEBUG(3) << text.str();
1640 }
1641
1642 if (j->m_criteria.get_classes_subscription().empty() && j->m_criteria.get_objects_subscription().empty())
1643 {
1644 try
1645 {
1646 TLOG_DEBUG(3) << "*** Invoke callback " << (void *)j << " with\n" << changes;
1647 (*(j->m_cb))(changes, j->m_param);
1648 }
1649 catch (const ers::Issue &ex)
1650 {
1651 ers::error(dunedaq::conffwk::Generic( ERS_HERE, "user callback thrown ers exception", ex));
1652 }
1653 catch (const std::exception &ex)
1654 {
1655 ers::error(dunedaq::conffwk::Generic( ERS_HERE, "user callback thrown std exception", ex));
1656 }
1657 catch (...)
1658 {
1659 ers::error(dunedaq::conffwk::Generic( ERS_HERE, "user callback thrown unknown exception"));
1660 }
1661 }
1662 else
1663 {
1664 std::vector<ConfigurationChange*> changes1;
1665
1666 for (const auto &i : changes)
1667 {
1668 const std::string &cname = i->get_class_name();
1669 ConfigurationChange *class_changes = nullptr;
1670
1671 ConfigurationSubscriptionCriteria::ObjectMap::const_iterator p = j->m_criteria.get_objects_subscription().find(cname);
1672 const bool found_obj_subscription(p != j->m_criteria.get_objects_subscription().end());
1673 const bool found_class_subscription(j->m_criteria.get_classes_subscription().find(cname) != j->m_criteria.get_classes_subscription().end());
1674
1675 if (found_class_subscription || found_obj_subscription)
1676 class_changes = new ConfigurationChange(cname);
1677
1678 if (found_class_subscription)
1679 {
1680 for (const auto &k : i->m_modified)
1681 class_changes->m_modified.push_back(k);
1682
1683 for (const auto &k : i->m_created)
1684 class_changes->m_created.push_back(k);
1685
1686 for (const auto &k : i->m_removed)
1687 class_changes->m_removed.push_back(k);
1688 }
1689
1690 if (found_obj_subscription)
1691 {
1692 for (const auto &obj_id : i->m_modified)
1693 if (p->second.find(obj_id) != p->second.end())
1694 class_changes->m_modified.push_back(obj_id);
1695
1696 for (const auto &obj_id : i->m_removed)
1697 if (p->second.find(obj_id) != p->second.end())
1698 class_changes->m_removed.push_back(obj_id);
1699 }
1700
1701 // the changes for given class can be empty if there is subscription on objects of given class, but no such objects were modified
1702 if (class_changes)
1703 {
1704 if (class_changes->m_modified.empty() && class_changes->m_created.empty() && class_changes->m_removed.empty())
1705 delete class_changes;
1706 else
1707 changes1.push_back(class_changes);
1708 }
1709 }
1710
1711 if (!changes1.empty())
1712 {
1713 TLOG_DEBUG(3) << "*** Invoke callback " << (void *)j << " with\n" << changes1;
1714
1715 try
1716 {
1717 (*(j->m_cb))(changes1, j->m_param);
1718 }
1719 catch (const ers::Issue &ex)
1720 {
1721 ers::error(dunedaq::conffwk::Generic( ERS_HERE, "user callback thrown ers exception", ex));
1722 }
1723 catch (const std::exception &ex)
1724 {
1725 ers::error(dunedaq::conffwk::Generic( ERS_HERE, "user callback thrown std exception", ex));
1726 }
1727 catch (...)
1728 {
1729 ers::error(dunedaq::conffwk::Generic( ERS_HERE, "user callback thrown unknown exception"));
1730 }
1731
1732 for (const auto &i : changes1)
1733 delete i;
1734 }
1735 }
1736 }
1737 }
1738
1739 TLOG_DEBUG(3) <<"*** Leave Configuration::system_cb()";
1740}
1741
1742
1743void
1745{
1746 TLOG_DEBUG(3) <<"*** Enter Configuration::system_pre_cb()";
1747
1748 std::lock_guard<std::mutex> scoped_lock(conf->m_else_mutex);
1749
1750 for(auto& j : conf->m_pre_callbacks)
1751 {
1752 TLOG_DEBUG(3) << "*** Invoke callback " << (void *)(j);
1753 (*(j->m_cb))(j->m_param);
1754 }
1755
1756 TLOG_DEBUG(3) <<"*** Leave Configuration::system_pre_cb()";
1757}
1758
1759
1760void
1761ConfigurationChange::add(std::vector<ConfigurationChange*> &changes, const std::string &class_name, const std::string &obj_name, const char action)
1762{
1763 ConfigurationChange *class_changes = nullptr;
1764
1765 for (const auto &c : changes)
1766 if (class_name == c->get_class_name())
1767 {
1768 class_changes = c;
1769 break;
1770 }
1771
1772 if (!class_changes)
1773 {
1774 class_changes = new ConfigurationChange(class_name);
1775 changes.push_back(class_changes);
1776 }
1777
1778 std::vector<std::string>& clist = (
1779 action == '+' ? class_changes->m_created :
1780 action == '-' ? class_changes->m_removed :
1781 class_changes->m_modified
1782 );
1783
1784 clist.push_back(obj_name);
1785}
1786
1787
1788void
1789ConfigurationChange::clear(std::vector<ConfigurationChange*> &changes)
1790{
1791 for (const auto &i : changes)
1792 delete i;
1793
1794 changes.clear();
1795}
1796
1797
1798static void
1799print_svect(std::ostream& s, const std::vector<std::string>& v, const char * name)
1800{
1801 s << " * " << v.size() << name;
1802
1803 for (auto i = v.begin(); i != v.end(); ++i)
1804 {
1805 s << ((i == v.begin()) ? ": " : ", ");
1806 s << '\"' << *i << '\"';
1807 }
1808
1809 s << std::endl;
1810}
1811
1812
1813std::ostream&
1814operator<<(std::ostream &s, const ConfigurationChange &c)
1815{
1816 s << " changes for class \'" << c.get_class_name() << "\' include:\n";
1817
1818 print_svect(s, c.get_modified_objs(), " modified object(s)");
1819 print_svect(s, c.get_created_objs(), " created object(s)");
1820 print_svect(s, c.get_removed_objs(), " removed object(s)");
1821
1822 return s;
1823}
1824
1825
1826std::ostream&
1827operator<<(std::ostream &s, const std::vector<ConfigurationChange*> &v)
1828{
1829 s << "There are configuration changes in " << v.size() << " classes:\n";
1830
1831 for (const auto &i : v)
1832 s << *i;
1833
1834 return s;
1835}
1836
1837void
1838Configuration::print(std::ostream &s) const noexcept
1839{
1840 s << "Configuration object:\n Inheritance Hierarchy (class - all it's superclasses):\n";
1841
1842 for (const auto &i : p_superclasses)
1843 {
1844 s << " * \'" << *i.first << "\' - ";
1845 if (i.second.empty())
1846 s << "(null)";
1847 else
1848 for (auto j = i.second.begin(); j != i.second.end(); ++j)
1849 {
1850 if (j != i.second.begin())
1851 s << ", ";
1852 s << '\'' << **j << '\'';
1853 }
1854 s << std::endl;
1855 }
1856}
1857
1858
1859bool
1860Configuration::try_cast(const std::string& target, const std::string& source) noexcept
1861{
1862 return is_superclass_of(target, source);
1863}
1864
1865bool
1866Configuration::try_cast(const std::string *target, const std::string *source) noexcept
1867{
1868 return is_superclass_of(target, source);
1869}
1870
1871bool
1872Configuration::is_superclass_of(const std::string& base_class, const std::string& child_class) noexcept
1873{
1874 return is_superclass_of(&DalFactory::instance().get_known_class_name_ref(base_class), &DalFactory::instance().get_known_class_name_ref(child_class));
1875}
1876
1877bool
1878Configuration::is_superclass_of(const std::string *base_class, const std::string *child_class) noexcept
1879{
1880 if (base_class == child_class)
1881 {
1882 TLOG_DEBUG(50) << "cast \'" << *child_class << "\' => \'" << *base_class << "\' is allowed (equal classes)";
1883 return true;
1884 }
1885
1886 conffwk::fmap<conffwk::fset>::iterator i = p_superclasses.find(child_class);
1887
1888 if (i == p_superclasses.end())
1889 {
1890 TLOG_DEBUG(50) << "cast \'" << *child_class << "\' => \'" << *base_class << "\' is not possible (base class is not loaded)";
1891 return false;
1892 }
1893
1894 if (i->second.find(base_class) != i->second.end())
1895 {
1896 TLOG_DEBUG(50) << "cast \'" << *child_class << "\' => \'" << *base_class << "\' is allowed (use inheritance)";
1897 return true;
1898 }
1899
1900 TLOG_DEBUG(50) << "cast \'" << *child_class << "\' => \'" << *base_class << "\' is not allowed (class \'" << *child_class << "\' has no \'" << *base_class << "\' as a superclass)";
1901
1902 return false;
1903}
1904
1905
1906std::ostream&
1907operator<<(std::ostream &s, const Configuration &c)
1908{
1909 c.print(s);
1910 return s;
1911}
1912
1913// std::ostream&
1914// operator<<(std::ostream& s, const DalObject * obj)
1915// {
1916// if (obj == nullptr)
1917// DalObject::p_null(s);
1918// else if (obj->is_deleted())
1919// s << "(deleted object " << obj->UID() << '@' << obj->class_name() << ')';
1920// else
1921// s << '\'' << obj->UID() << '@' << obj->class_name() << '\'';
1922
1923// return s;
1924// }
1925
1926// std::ostream&
1927// operator<<(std::ostream& s, const DalObject * obj)
1928// {
1929// if (obj == nullptr)
1930// DalObject::p_null(s);
1931// else if (obj->is_deleted())
1932// s << "(deleted object " << obj->UID() << '@' << obj->class_name() << ')';
1933// else
1934// s << '\'' << obj->UID() << '@' << obj->class_name() << '\'';
1935
1936// return s;
1937// }
1938
1939std::string
1940Configuration::mk_ref_ex_text(const char * what, const std::string& cname, const std::string& rname, const ConfigObject& obj) noexcept
1941{
1942 std::ostringstream text;
1943 text << "failed to get " << what << " of class \'" << cname << "\' via relationship \'" << rname << "\' of object \'" << obj << '\'';
1944 return text.str();
1945}
1946
1947
1948std::string
1949Configuration::mk_ref_by_ex_text(const std::string& cname, const std::string& rname, const ConfigObject& obj) noexcept
1950{
1951 std::ostringstream text;
1952 text << "failed to get objects of class \'" << cname << "\' referencing object \'" << obj << "\' via relationship \'" << rname << '\'';
1953 return text.str();
1954}
1955
1956// std::vector<const DalObject*>
1957// Configuration::make_dal_objects(std::vector<ConfigObject>& objs, bool upcast_unregistered)
1958// {
1959// std::vector<const DalObject*> result;
1960
1961// for (auto &i : objs)
1962// // if (DalObject *o = DalFactory::instance().get(*this, i, i.UID(), upcast_unregistered)) // FIXME: 2018-11-09: pass right UID()
1963// if (DalObject *o = m_registry.get(i,upcast_unregistered)) // FIXME: 2018-11-09: pass right UID()
1964// result.push_back(o);
1965
1966// return result;
1967// }
1968
1969// const DalObject*
1970// Configuration::make_dal_object(ConfigObject& obj, const std::string& uid, const std::string& class_name)
1971// {
1972 // return DalFactory::instance().get(*this, obj, uid, class_name);
1973 // return m_registry.get(*this, obj, uid, class_name);
1974// }
1975
1976
1977std::vector<const DalObject*>
1978Configuration::referenced_by(const DalObject& obj, const std::string& relationship_name,
1979 bool check_composite_only, bool upcast_unregistered,
1980 bool /*init*/, unsigned long rlevel,
1981 const std::vector<std::string> * rclasses)
1982{
1983 try
1984 {
1985 std::vector<ConfigObject> objs;
1986 std::lock_guard<std::mutex> scoped_lock(m_tmpl_mutex);
1987
1988 obj.p_obj.referenced_by(objs, relationship_name, check_composite_only, rlevel, rclasses);
1989 // return make_dal_objects(objs, upcast_unregistered);
1990 return m_registry.get(objs, upcast_unregistered);
1991 }
1992 catch (dunedaq::conffwk::Generic & ex)
1993 {
1994 throw(dunedaq::conffwk::Generic( ERS_HERE, mk_ref_by_ex_text("DalObject", relationship_name, obj.p_obj).c_str(), ex ) );
1995 }
1996}
1997
1998std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
1999Configuration::attributes_pybind(const std::string& class_name, bool all) {
2000
2001 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> all_attributes_properties;
2002
2003 const dunedaq::conffwk::class_t& c = this->get_class_info(class_name, !all);
2004
2005 for (const auto& ap : c.p_attributes) {
2006 std::unordered_map<std::string, std::string> attribute_properties;
2007 attribute_properties["type"] = dunedaq::conffwk::attribute_t::type(ap.p_type);
2008
2009 attribute_properties["range"] = ap.p_range.empty() ? "None" : ap.p_range;
2010
2011 attribute_properties["description"] = ap.p_description;
2012
2013 attribute_properties["multivalue"] = ap.p_is_multi_value ? "True" : "False";
2014
2015 attribute_properties["not-null"] = ap.p_is_not_null ? "True" : "False";
2016
2017 attribute_properties["init-value"] = ap.p_default_value.empty() ? "None" : ap.p_default_value;
2018
2019 all_attributes_properties[ap.p_name] = attribute_properties;
2020 }
2021
2022 return all_attributes_properties;
2023}
2024
2025std::vector<std::string>
2027 std::vector<std::string> classes;
2028 for (const auto& it : this->superclasses()) {
2029 classes.push_back(*it.first);
2030 }
2031
2032 return classes;
2033}
2034
2036Configuration::create_and_return_obj_pybind(const std::string& at, const std::string& class_name, const std::string& id) {
2037 auto co = new ConfigObject;
2038 this->create(at, class_name, id, *co);
2039 return co;
2040}
2041
2043Configuration::create_and_return_obj_pybind(const ConfigObject& at, const std::string& class_name, const std::string& id) \
2044{
2045 auto co = new ConfigObject;
2046 this->create(at, class_name, id, *co);
2047 return co;
2048}
2049
2051Configuration::get_obj_pybind(const std::string& class_name, const std::string& id)
2052{
2053 auto co = new ConfigObject;
2054 this->get(class_name, id, *co);
2055 if (co->is_null()) {
2056 delete co;
2057 co = nullptr;
2058 }
2059 return co;
2060}
2061
2062std::vector<ConfigObject>*
2063Configuration::get_objs_pybind(const std::string& class_name, const std::string& query) {
2064 auto objs = new std::vector<ConfigObject>;
2065 this->get(class_name, *objs, query);
2066 return objs;
2067}
2068
2069
2070std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
2071Configuration::relations_pybind(const std::string& class_name, bool all) {
2072
2073 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> all_relationships_properties;
2074
2075 const dunedaq::conffwk::class_t& c = this->get_class_info(class_name, !all);
2076
2077 for (const auto& rp : c.p_relationships) {
2078 std::unordered_map<std::string, std::string> relationship_properties;
2079
2080 relationship_properties["type"] = rp.p_type;
2081 relationship_properties["description"] = rp.p_description;
2082 relationship_properties["multivalue"] = (rp.p_cardinality == dunedaq::conffwk::zero_or_many || rp.p_cardinality == dunedaq::conffwk::one_or_many) ? "True" : "False";
2083 relationship_properties["aggregation"] = rp.p_is_aggregation ? "True" : "False";
2084 relationship_properties["not-null"] = (rp.p_cardinality == dunedaq::conffwk::only_one || rp.p_cardinality == dunedaq::conffwk::one_or_many) ? "True" : "False";
2085
2086 all_relationships_properties[rp.p_name] = relationship_properties;
2087 }
2088
2089 return all_relationships_properties;
2090}
2091
2092std::list<std::string>*
2093Configuration::return_includes_pybind(const std::string& db_name) {
2094 auto l = new std::list<std::string>;
2095 this->get_includes(db_name, *l);
2096 return l;
2097}
2098
2099std::vector<std::string>
2100Configuration::subclasses_pybind(const std::string& class_name, bool all) {
2101
2102 const dunedaq::conffwk::class_t& c = this->get_class_info(class_name, !all);
2103 return c.p_subclasses;
2104}
2105
2106std::vector<std::string>
2107Configuration::superclasses_pybind(const std::string& class_name, bool all) {
2108
2109 const dunedaq::conffwk::class_t& c = this->get_class_info(class_name, !all);
2110 return c.p_superclasses;
2111}
2112
2113
2114} // namespace conffwk
2115} // namespace dunedaq
#define ERS_DEFINE_ISSUE_CXX(namespace_name, class_name, message, attributes)
#define ERS_DEFINE_ISSUE_BASE_CXX(namespace_name, class_name, base_class_name, message, base_attributes, attributes)
#define ERS_HERE
Represents database objects.
const std::string & UID() const noexcept
Return object identity.
Describes changes inside a class returned by the notification mechanism.
Definition Change.hpp:35
const std::vector< std::string > & get_created_objs() const
Return vector of identies of created objects.
Definition Change.hpp:54
std::vector< std::string > m_removed
Definition Change.hpp:110
static void clear(std::vector< ConfigurationChange * > &changes)
Helper method to clear vector of changes (pointers).
ConfigurationChange(const ConfigurationChange &)
std::vector< std::string > m_created
Definition Change.hpp:109
std::vector< std::string > m_modified
Definition Change.hpp:108
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.
Definition Change.hpp:49
const std::vector< std::string > & get_removed_objs() const
Return vector of identies of removed objects.
Definition Change.hpp:59
Provides pure virtual interface used by the Configuration class.
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.
std::map< std::string, std::set< std::string > > ObjectMap
The map stores full subsription information.
Defines base class for cache of template objects.
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)
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
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 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.
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...
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.
std::atomic< uint_least64_t > p_number_of_template_object_created
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
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.
std::vector< std::string > get_class_list() const
conffwk::map< dunedaq::conffwk::class_t * > p_all_classes_desc_cache
void unread_all_objects(bool unread_implementation_objs=false) noexcept
Mark object of given template class as unread (multi-thread unsafe).
std::deque< std::set< std::string > > find_class_domains()
CallbackSubscription * CallbackId
Callback identifier.
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 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
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.
Definition DalObject.hpp:45
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.
Try to access deleted DAL object.
Definition Errors.hpp:72
Generic configuration exception.
Try to access non-existent object or class.
Definition Errors.hpp:47
Base class for any user define issue.
Definition Issue.hpp:69
conffwk entry point
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
std::ostream & operator<<(std::ostream &, const ConfigurationChange &)
Including Qt Headers.
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 init_regex(std::unique_ptr< std::regex > &ptr, const std::string &str, const char *what)
static bool check_prefetch_needs()
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)
int debug_level()
Definition ers.hpp:66
void error(const Issue &issue)
Definition ers.hpp:81
static const char * type(type_t type)
static const char * format2str(int_format_t format)
static const char * card2str(cardinality_t cardinality)
Factory couldn t std::string alg_name Invalid configuration error
Definition Issues.hpp:34