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
15 TLOG_DEBUG(50) << "Building object " << obj.UID() << " of class " << obj.class_name() << " and returning class "
16 << T::s_class_name;
17
18 // Ensure that T is a superclass of (or the same class as) obj.class_name()
19 if (not(m_confdb.is_superclass_of(obj.class_name(), T::s_class_name) ||
20 m_confdb.is_superclass_of(T::s_class_name, obj.class_name()))) {
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 TLOG_DEBUG(50) << "Returning " << (void*)result;
59
60 return result;
61}
62
63//-----------------------------------------------------------------------------
64template<class T>
65T*
66DalRegistry::get(const std::string& name,
67 bool init_children,
68 bool init_object,
69 unsigned long rlevel,
70 const std::vector<std::string>* rclasses)
71{
72
73 TLOG_DEBUG(50) << "Building object " << name;
74
75 const std::string& ref_name = DalFactory::instance().get_known_class_name_ref(T::s_class_name);
76
77 TLOG_DEBUG(50) << "Ref name is " << ref_name;
78
79 // Find the class domain of T
80 auto it_dom = m_class_domain_map.find(&ref_name);
81
82 // Class not known, this should not happen
83 if (it_dom == m_class_domain_map.end()) {
84 const std::string id(name + '@' + T::s_class_name);
85 throw dunedaq::conffwk::NotFound(ERS_HERE, "object", id.c_str());
86 }
87
88 auto& domain = m_cache_domains[it_dom->second];
89
90 TLOG_DEBUG(50) << "Class domain for " << ref_name << " is " << it_dom->second;
91
92 auto it_ptr = domain.cache.find(ref_name);
93
94 TLOG_DEBUG(50) << "Cache found";
95
96 if (it_ptr == domain.cache.end()) {
97 try {
98 // Search for an ConfigObject of id 'name' of class 'T'
100 m_confdb._get(T::s_class_name, name, obj, rlevel, rclasses);
101
102 DalObject*& dal_ptr(domain.cache[obj.m_impl->m_id]);
103
104 T* result = dynamic_cast<T*>(dal_ptr);
105
106 if (result == nullptr) {
107 // result = new T(*this, obj);
108 dal_ptr = DalFactory::instance().make(*this, obj, T::s_class_name);
109
110 TLOG_DEBUG(50) << "Casting " << obj.UID() << " of class " << obj.class_name() << " to " << T::s_class_name;
111 result = dynamic_cast<T*>(dal_ptr);
112 TLOG_DEBUG(50) << "From " << (void*)dal_ptr << " to " << (void*)result;
113
114 if (init_object) {
115 std::lock_guard<std::mutex> scoped_lock(result->m_mutex);
116 result->init(init_children);
117 }
118 } else if (obj.m_impl != result->p_obj.m_impl) {
119 std::lock_guard<std::mutex> scoped_lock(result->m_mutex);
120 result->set(obj); // update implementation object; to be used in case if the object is re-created
121 }
122
123 return result;
124
125 } catch (dunedaq::conffwk::NotFound& ex) {
126
127 if (!strcmp(ex.get_type(), "class")) {
128
129 std::ostringstream text;
130 text << "wrong database schema, cannot find class \"" << ex.get_data() << '\"';
131
132 throw dunedaq::conffwk::Generic(ERS_HERE, text.str().c_str());
133 }
134
135 return nullptr;
136 }
137 }
138
139 std::cout << "Found " << (void*)it_ptr->second << std::endl;
140 return dynamic_cast<T*>(it_ptr->second);
141}
142
143//-----------------------------------------------------------------------------
144template<class T>
145T*
146DalRegistry::find(const std::string& id)
147{
148 std::lock_guard<std::mutex> scoped_lock(m_mutex);
149
150 auto it_dom = m_class_domain_map.find(&T::s_class_name);
151
152 if (it_dom == m_class_domain_map.end()) {
153 return nullptr;
154 }
155
156 auto& domain = m_cache_domains[it_dom.second];
157 auto it_obj = domain.cache.find(id);
158 return (it_obj != domain.cache.end() ? dynamic_cast<T*>(it_obj->second) : nullptr);
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(
172 ERS_HERE, Configuration::mk_ref_ex_text("an object", T::s_class_name, name, obj).c_str(), ex));
173 }
174
175 return ((!res.is_null()) ? this->get<T>(res, read_children, read_children) : nullptr);
176}
177
178// Get multiple relations from object and instantiate result with it.
179template<class T>
180void
181DalRegistry::_ref(ConfigObject& obj, const std::string& name, std::vector<const T*>& results, bool read_children)
182{
183
184 std::vector<ConfigObject> objs;
185
186 results.clear();
187
188 try {
189 obj.get(name, objs);
190 results.reserve(objs.size());
191
192 for (auto& i : objs) {
193 auto ptr = this->get<T>(i, read_children, read_children);
194 results.push_back(ptr);
195 }
196 } catch (dunedaq::conffwk::Generic& ex) {
197 throw(dunedaq::conffwk::Generic(
198 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
208 std::lock_guard<std::mutex> scoped_lock(m_mutex);
209
210 auto it_dom = m_class_domain_map.find(&T::s_class_name);
211 if (it_dom == m_class_domain_map.end()) {
212 return false;
213 }
214
215 for (const auto& [uid, ptr] : m_cache_domains[it_dom->second].cache) {
216 if (ptr == object) {
217 return true;
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
230 this->update(T::s_class_name, modified, removed, created);
231}
232
233//-----------------------------------------------------------------------------
234template<class T>
235void
237{
238
239 // Find the class domain of T
240 auto it_dom = m_class_domain_map.find(&DalFactory::instance().get_known_class_name_ref(T::s_class_name));
241
242 // Class not known, this should not happen
243 if (it_dom == m_class_domain_map.end()) {
244 throw dunedaq::conffwk::NotFound(ERS_HERE, "class", T::s_class_name.c_str());
245 }
246
247 auto& domain = m_cache_domains[it_dom->second];
248
249 // Loop over the objects in the domain and reset those inheriting from T
250 for (const auto& [uid, ptr] : domain.cache) {
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
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.
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.
std::unordered_map< uint, DalDomain > m_cache_domains
bool is_valid(const T *object) noexcept
Checks validity of pointer to an objects of given user class.
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:116
The DUNE-DAQ namespace.
msgpack::object obj