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