DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
DalRegistry.hxx
Go to the documentation of this file.
1#ifndef __DUNEDAQ_CONFFWK_DALREGISTRY_HXX__
2#define __DUNEDAQ_CONFFWK_DALREGISTRY_HXX__
3
4#include "conffwk/Errors.hpp"
5
6namespace dunedaq {
7namespace conffwk {
8
9//-----------------------------------------------------------------------------
10template<class T>
11T *
12DalRegistry::get(ConfigObject& obj, bool init_children, bool init_object) {
13
14 TLOG_DEBUG(50) << "Building object " << obj.UID() << " of class " << obj.class_name() << " and returning class " << T::s_class_name;
15
16 // Ensure that T is a superclass of (or the same class as) obj.class_name()
17 if ( not (
18 m_confdb.is_superclass_of(obj.class_name(), T::s_class_name) ||
19 m_confdb.is_superclass_of(T::s_class_name, obj.class_name())
20 )) {
21 // do nothing if this is the case
22 return nullptr;
23 }
24
25 // Find the class domain of T
26 auto it_dom = m_class_domain_map.find(&DalFactory::instance().get_known_class_name_ref(T::s_class_name));
27
28 // Class not known, this should not happen
29 if ( it_dom == m_class_domain_map.end() ) {
30 const std::string id(obj.UID() + '@' + obj.class_name());
31 throw dunedaq::conffwk::NotFound(ERS_HERE, "object", id.c_str());
32 }
33
34 auto& domain = m_cache_domains[it_dom->second];
35
36 DalObject*& dal_ptr(domain.cache[obj.m_impl->m_id]);
37 T* result = dynamic_cast<T*>(dal_ptr);
38
39 if (result == nullptr) {
40 // result = new T(*this, obj);
41 dal_ptr = DalFactory::instance().make(*this, obj, T::s_class_name);
42
43 TLOG_DEBUG(50) << "Casting " << obj.UID() << " of class " << obj.class_name() << " to " << T::s_class_name;
44 result = dynamic_cast<T*>(dal_ptr);
45 TLOG_DEBUG(50) << "From " << (void*)dal_ptr << " to " << (void*)result;
46
47 if (init_object) {
48 std::lock_guard<std::mutex> scoped_lock(result->m_mutex);
49 result->init(init_children);
50 }
51
52 } else if (obj.m_impl != result->p_obj.m_impl) {
53
54 std::lock_guard<std::mutex> scoped_lock(result->m_mutex);
55 result->set(obj); // update implementation object; to be used in case if the object is re-created
56
57 }
58
59 TLOG_DEBUG(50) << "Returning " << (void*)result;
60
61 return result;
62}
63
64
65//-----------------------------------------------------------------------------
66template<class T> T *
67DalRegistry::get(const std::string& name, bool init_children, bool init_object, unsigned long rlevel, const std::vector<std::string> * rclasses) {
68
69 TLOG_DEBUG(50) << "Building object " << name;
70
71 const std::string& ref_name = DalFactory::instance().get_known_class_name_ref(T::s_class_name);
72
73 TLOG_DEBUG(50) << "Ref name is " << ref_name;
74
75
76 // Find the class domain of T
77 auto it_dom = m_class_domain_map.find(&ref_name);
78
79 // Class not known, this should not happen
80 if ( it_dom == m_class_domain_map.end() ) {
81 const std::string id(name + '@' + T::s_class_name);
82 throw dunedaq::conffwk::NotFound(ERS_HERE, "object", id.c_str());
83 }
84
85 auto& domain = m_cache_domains[it_dom->second];
86
87 TLOG_DEBUG(50) << "Class domain for " << ref_name << " is " << it_dom->second;
88
89 auto it_ptr = domain.cache.find(ref_name);
90
91 TLOG_DEBUG(50) << "Cache found";
92
93 if ( it_ptr == domain.cache.end()) {
94 try {
95 // Search for an ConfigObject of id 'name' of class 'T'
97 m_confdb._get(T::s_class_name, name, obj, rlevel, rclasses);
98
99 DalObject*& dal_ptr(domain.cache[obj.m_impl->m_id]);
100
101 T* result = dynamic_cast<T*>(dal_ptr);
102
103
104 if (result == nullptr) {
105 // result = new T(*this, obj);
106 dal_ptr = DalFactory::instance().make(*this, obj, T::s_class_name);
107
108 TLOG_DEBUG(50) << "Casting " << obj.UID() << " of class " << obj.class_name() << " to " << T::s_class_name;
109 result = dynamic_cast<T*>(dal_ptr);
110 TLOG_DEBUG(50) << "From " << (void*)dal_ptr << " to " << (void*)result;
111
112 if (init_object) {
113 std::lock_guard<std::mutex> scoped_lock(result->m_mutex);
114 result->init(init_children);
115 }
116 } else if (obj.m_impl != result->p_obj.m_impl) {
117 std::lock_guard<std::mutex> scoped_lock(result->m_mutex);
118 result->set(obj); // update implementation object; to be used in case if the object is re-created
119 }
120
121 return result;
122
123 } catch (dunedaq::conffwk::NotFound& ex) {
124
125 if (!strcmp(ex.get_type(), "class")) {
126
127 std::ostringstream text;
128 text << "wrong database schema, cannot find class \"" << ex.get_data() << '\"';
129
130 throw dunedaq::conffwk::Generic(ERS_HERE, text.str().c_str());
131 }
132
133 return nullptr;
134 }
135 }
136
137 std::cout << "Found " << (void*)it_ptr->second << std::endl;
138 return dynamic_cast<T*>(it_ptr->second);
139
140}
141
142
143//-----------------------------------------------------------------------------
144template<class T>
145T *
146DalRegistry::find(const std::string & id) {
147 std::lock_guard<std::mutex> scoped_lock(m_mutex);
148
149 auto it_dom = m_class_domain_map.find(&T::s_class_name);
150
151 if ( it_dom == m_class_domain_map.end()) {
152 return nullptr;
153 }
154
155 auto& domain = m_cache_domains[it_dom.second];
156 auto it_obj = domain.cache.find(id);
157 return (it_obj != domain.cache.end() ? dynamic_cast<T*>(it_obj->second) : nullptr);
158}
159
160
161//-----------------------------------------------------------------------------
162template<class T>
163const T*
164DalRegistry::_ref(ConfigObject& obj, const std::string& name, bool read_children)
165{
166 ConfigObject res;
167
168 try {
169 obj.get(name, res);
170 } catch (dunedaq::conffwk::Generic& ex) {
171 throw(dunedaq::conffwk::Generic(ERS_HERE, Configuration::mk_ref_ex_text("an object", T::s_class_name, name, obj).c_str(), ex));
172 }
173
174 return ((!res.is_null()) ? this->get<T>(res, read_children, read_children) : nullptr);
175}
176
177
178
179// Get multiple relations from object and instantiate result with it.
180template<class T>
181void
182DalRegistry::_ref(ConfigObject& obj, const std::string& name, std::vector<const T*>& results, bool read_children)
183{
184
185 std::vector<ConfigObject> objs;
186
187 results.clear();
188
189 try {
190 obj.get(name, objs);
191 results.reserve(objs.size());
192
193 for (auto& i : objs) {
194 auto ptr = this->get<T>(i, read_children, read_children);
195 results.push_back(ptr);
196 }
197 } catch (dunedaq::conffwk::Generic& ex) {
198 throw(dunedaq::conffwk::Generic(ERS_HERE, Configuration::mk_ref_ex_text("objects", T::s_class_name, name, obj).c_str(), ex));
199 }
200}
201
202//-----------------------------------------------------------------------------
203template<class T>
204bool
205DalRegistry::is_valid(const T * object) noexcept {
206
207 std::lock_guard<std::mutex> scoped_lock(m_mutex);
208
209 auto it_dom = m_class_domain_map.find(&T::s_class_name);
210 if ( it_dom == m_class_domain_map.end()) {
211 return false;
212 }
213
214 for( const auto& [uid, ptr] : m_cache_domains[it_dom->second].cache ) {
215 if ( ptr == object ) {
216 return true;
217 }
218 }
219}
220
221
222//-----------------------------------------------------------------------------
223template<class T>
224void
225DalRegistry::update(const std::vector<std::string>& modified,
226 const std::vector<std::string>& removed,
227 const std::vector<std::string>& created) {
228
229 this->update(T::s_class_name, modified, removed, created);
230}
231
232
233//-----------------------------------------------------------------------------
234template<class T>
235void
237
238 // Find the class domain of T
239 auto it_dom = m_class_domain_map.find(&DalFactory::instance().get_known_class_name_ref(T::s_class_name));
240
241 // Class not known, this should not happen
242 if ( it_dom == m_class_domain_map.end() ) {
243 throw dunedaq::conffwk::NotFound(ERS_HERE, "class", T::s_class_name.c_str());
244 }
245
246 auto& domain = m_cache_domains[it_dom->second];
247
248 // Loop over the objects in the domain and reset those inheriting from T
249 for( const auto& [uid, ptr] : domain.cache ) {
250
251
252 T* obj_ptr = dynamic_cast<T*>(ptr);
253
254 if (!obj_ptr)
255 continue;
256
257 std::lock_guard<std::mutex> scoped_lock(domain.mutex);
258 obj_ptr->p_was_read = false;
259 }
260}
261
262} // namespace conffwk
263} // namespace dunedaq
264
265#endif /*__DUNEDAQ_CONFFWK_DALREGISTRY_HXX__ */
#define ERS_HERE
Represents database objects.
bool is_null() const noexcept
Check if object's implementation points to null.
void _get(const std::string &class_name, const std::string &id, ConfigObject &object, unsigned long rlevel, const std::vector< std::string > *rclasses)
static std::string mk_ref_ex_text(const char *what, const std::string &cname, const std::string &rname, const ConfigObject &obj) noexcept
bool is_superclass_of(const std::string &target, const std::string &source) noexcept
The base class for any generated DAL object.
Definition DalObject.hpp:45
DalObject * get(ConfigObject &obj, bool upcast_unregistered=false)
void _reset_objects()
Update state of objects after abort operations.
void update(const std::vector< std::string > &modified, const std::vector< std::string > &removed, const std::vector< std::string > &created)
Update cache of objects in case of modification.
std::unordered_map< uint, DalDomain > m_cache_domains
const T * _ref(ConfigObject &obj, const std::string &name, bool read_children)
Get signle value of object's relation and instantiate result with it (multi-thread safe).
conffwk::fmap< uint > m_class_domain_map
T * find(const std::string &id)
Find template object using ID.
bool is_valid(const T *object) noexcept
Checks validity of pointer to an objects of given user class.
Generic configuration exception.
Try to access non-existent object or class.
Definition Errors.hpp:47
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
Including Qt Headers.