Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS dbe source for the DUNE DAQ project.
3 : // Fork baseline commit: dbe-02-12-17 (2022-05-12).
4 : // Renamed since fork: no.
5 :
6 : /*
7 : * dbcontroller.cpp
8 : *
9 : * Created on: Oct 30, 2015
10 : * Author: lgeorgop
11 : */
12 :
13 : #include "dbe/dbcontroller.hpp"
14 : #include "dbe/config_reference_copy.hpp"
15 : #include "dbe/messenger.hpp"
16 : #include "dbe/msghandler.hpp"
17 :
18 : #include <utility>
19 :
20 : using namespace dunedaq::conffwk;
21 :
22 : namespace dbe
23 : {
24 : namespace inner
25 : {
26 :
27 : namespace configobject
28 : {
29 : //------------------------------------------------------------------------------------------
30 : // NAMESPACE DBE::INNER::CONFIGOBJECT
31 : //------------------------------------------------------------------------------------------
32 :
33 : //------------------------------------------------------------------------------------------
34 : template<typename T>
35 0 : std::vector<T> ref_interface<T>::referenced_by(std::string const & name,
36 : bool check_composite_only) const
37 : {
38 0 : std::vector<ConfigObject> referees;
39 0 : std::vector<tref> result;
40 :
41 0 : static_cast<ConfigObject &>(*this).referenced_by(referees, name, check_composite_only);
42 :
43 0 : for (ConfigObject const & x : referees)
44 : {
45 : try
46 : {
47 0 : result.push_back(inner::dbcontroller::get(
48 0 : { x.UID(), x.class_name() }));
49 : }
50 0 : catch (daq::dbe::config_object_retrieval_result_is_null const & e)
51 : {
52 : // Nothing needed to do here, this is normal, just the query has resulted in null
53 : }
54 : }
55 :
56 0 : return result;
57 0 : }
58 :
59 : template
60 : std::vector<tref> ref_interface<tref>::referenced_by(std::string const &, bool) const;
61 :
62 : //------------------------------------------------------------------------------------------
63 :
64 : //------------------------------------------------------------------------------------------
65 0 : template<typename T> void gref<T>::record(tref const & o)
66 : {
67 0 : t_extractor obj(o);
68 0 : for (auto const & linked : obj.relations)
69 : {
70 0 : for (auto const & candidate : linked.second)
71 : {
72 0 : record(candidate.ref());
73 : }
74 : }
75 0 : this_remove_stack.push_back(obj);
76 0 : }
77 :
78 0 : template<typename T> void gref<T>::post()
79 : {
80 0 : type_extractor_stack acopy;
81 0 : std::swap(acopy, this_remove_stack);
82 :
83 0 : while (not acopy.empty())
84 : {
85 0 : t_extractor candidate = acopy.front();
86 : // Keep only objects that have been deleted
87 0 : if (not dbe::config::api::info::has_obj(candidate.ref.class_name(),
88 0 : candidate.ref.UID()))
89 : {
90 0 : this_remove_stack.push_back(candidate);
91 : }
92 0 : acopy.pop_front();
93 : }
94 0 : }
95 :
96 0 : template<typename T> void gref<T>::notify(config_action_notifiable tele)
97 : {
98 0 : if (this_notify_stack.empty())
99 : {
100 0 : for (typename type_extractor_stack::value_type const & val : this_remove_stack)
101 : {
102 0 : tele(val.ref);
103 : }
104 : }
105 : else
106 : {
107 0 : for (typename type_ref_container::value_type const & val : this_notify_stack)
108 : {
109 0 : tele(val);
110 : }
111 : }
112 0 : }
113 :
114 0 : template<typename T> tref gref<T>::rebuild()
115 : {
116 0 : if (not this_remove_stack.empty())
117 : {
118 0 : for (;;)
119 : {
120 0 : t_extractor record = this_remove_stack.front();
121 0 : tref last = dbcontroller::create_object_request(record.toimage());
122 0 : this_remove_stack.pop_front();
123 0 : if (not last.is_null())
124 : {
125 0 : this_notify_stack.push_back(last);
126 : }
127 0 : if (this_remove_stack.empty())
128 : {
129 0 : return last;
130 : }
131 : }
132 : }
133 0 : throw daq::dbe::gref_empty_internal_queue_is_invalid_state(ERS_HERE);
134 : }
135 :
136 : template<typename T> bool gref<T>::is_null() const
137 : {
138 : return this_remove_stack.front().is_null();
139 : }
140 : //------------------------------------------------------------------------------------------
141 :
142 : //------------------------------------------------------------------------------------------
143 : template<typename T>
144 0 : tref authorized_getter<T, tref>::operator()(std::string const & key)
145 : {
146 0 : ConfigObject voisin
147 0 : { this->that->template getdirect<ConfigObject>(key) };
148 :
149 0 : if (voisin.is_null())
150 : {
151 0 : throw daq::dbe::config_object_retrieval_result_is_null(ERS_HERE,key);
152 : }
153 :
154 : // There is no need to catch the resulting exception from get because the object
155 : // has just been retrieved from the database, and the call to get just generates
156 : // the tref and adds the object to the internal lookup table.
157 0 : return dbcontroller::get({ voisin.UID(), voisin.class_name() });
158 0 : }
159 :
160 : template<typename T>
161 0 : std::vector<tref> authorized_getter<T, std::vector<tref>>::operator()(
162 : std::string const & key)
163 : {
164 0 : std::vector<ConfigObject> voisins
165 0 : { this->that->template getdirect<std::vector<ConfigObject>>(key) };
166 :
167 0 : std::vector<tref> references;
168 :
169 0 : for (ConfigObject const & voisin : voisins)
170 : {
171 : try
172 : {
173 0 : references.push_back(dbcontroller::get(
174 0 : { voisin.UID(), voisin.class_name() }));
175 : }
176 0 : catch (daq::dbe::config_object_retrieval_result_is_null const & ex)
177 : {
178 : // Actually there is no need to handle this error here ,
179 : // since the object will not be added to the result list of references,
180 : // and can be safely ignored
181 : }
182 : }
183 :
184 0 : return references;
185 0 : }
186 :
187 : template class authorized_getter<tref, tref> ;
188 : template class authorized_getter<tref, std::vector<tref>> ;
189 : //------------------------------------------------------------------------------------------
190 :
191 : }// end namespace configobject
192 :
193 : //------------------------------------------------------------------------------------------
194 : // NAMESPACE DBE::INNER
195 : //------------------------------------------------------------------------------------------
196 :
197 : dbcontroller::t_mutex dbcontroller::this_lock;
198 :
199 : //------------------------------------------------------------------------------------------
200 2 : dbcontroller::dbcontroller() = default;
201 : //------------------------------------------------------------------------------------------
202 :
203 : //------------------------------------------------------------------------------------------
204 14 : dbcontroller & dbcontroller::ref()
205 : {
206 14 : static dbcontroller self;
207 14 : return self;
208 : }
209 : //------------------------------------------------------------------------------------------
210 :
211 : //------------------------------------------------------------------------------------------
212 6 : void dbcontroller::flush()
213 : {
214 6 : dbcontroller & me = dbcontroller::ref();
215 6 : locker l(me.this_lock);
216 6 : me.this_allobjects.clear();
217 6 : }
218 : //------------------------------------------------------------------------------------------
219 :
220 : //------------------------------------------------------------------------------------------
221 0 : std::vector<tref> dbcontroller::referenced_by(configobject::tref objref,
222 : std::string const & name,
223 : bool check_composite_only)
224 : {
225 0 : std::vector<ConfigObject> linked;
226 0 : objref.ref().referenced_by(linked, name, check_composite_only);
227 :
228 0 : std::vector<configobject::tref> references;
229 :
230 0 : for (ConfigObject const & anobj : linked)
231 : {
232 0 : try
233 : {
234 0 : references.push_back(get(
235 0 : { anobj.UID(), anobj.class_name() }));
236 : }
237 0 : catch (daq::dbe::config_object_retrieval_result_is_null const & e)
238 : {
239 : // nothing needed to do here, since this just signal that
240 : // some of the relation results are null
241 0 : }
242 : }
243 :
244 0 : return references;
245 0 : }
246 : //------------------------------------------------------------------------------------------
247 :
248 : //------------------------------------------------------------------------------------------
249 0 : template<typename T> configobject::gref<T> dbcontroller::delete_object_request(
250 : configobject::tref const & obj,
251 : typename configobject::gref<T>::config_action_notifiable notice)
252 : {
253 0 : configobject::gref<T> subgraph = dbcontroller::ref().remove<T>(obj);
254 0 : subgraph.notify(notice);
255 0 : return subgraph;
256 0 : }
257 :
258 : template
259 : configobject::gref<dbe::config_object_aggregates<std::string>>
260 : dbcontroller::delete_object_request (
261 : configobject::tref const &,
262 : configobject::gref<dbe::config_object_aggregates<std::string>>::config_action_notifiable);
263 :
264 : //------------------------------------------------------------------------------------------
265 :
266 : //------------------------------------------------------------------------------------------
267 : /*
268 : * Create an object in the database.
269 : *
270 : * If the object cannot be created an exception will be thrown
271 : * by the underlying database access layer, as it cannot be handled here.
272 : *
273 : * If the object is already in the underlying container the object reference will be updated
274 : * to point to the new object reference, transparently to user classes of the controller
275 : */
276 0 : configobject::tref dbcontroller::create_object_request(
277 : dbe::t_config_object_preimage const & image)
278 : {
279 0 : ConfigObject result = config::api::rwdacc::create_object(image.fn,
280 0 : image.ref.this_class,
281 0 : image.ref.this_name);
282 :
283 0 : tref el = dbcontroller::ref().insert(result);
284 0 : try
285 : {
286 0 : return dbe::config::api::rwdacc::set_object(el,image.attributes, image.relations);
287 : }
288 0 : catch (dunedaq::conffwk::Exception const & e)
289 : {
290 : // just need to remove the object from the underlying database
291 0 : dbcontroller::ref().remove<config_object_aggregator>(el);
292 0 : throw;
293 0 : }
294 0 : catch (daq::dbe::Exception const & e)
295 : {
296 : // just need to remove the object from the underlying database
297 0 : dbcontroller::ref().remove<config_object_aggregator>(el);
298 0 : throw;
299 0 : }
300 0 : }
301 :
302 : template<typename T> configobject::tref dbcontroller::create_object_request(
303 : configobject::aref<T> const & obj)
304 : {
305 : return dbcontroller::create_object_request(obj.this_object_image);
306 : }
307 :
308 : template<typename T> configobject::tref dbcontroller::create_object_request(
309 : configobject::gref<T> const & obj)
310 : {
311 : return obj.rebuild();
312 : }
313 :
314 0 : template<typename T> configobject::tref dbcontroller::create_object_request(
315 : configobject::gref<T> & obj,
316 : typename configobject::gref<T>::config_action_notifiable notice)
317 : {
318 0 : tref ret = obj.rebuild();
319 0 : obj.notify(notice);
320 0 : return ret;
321 0 : }
322 :
323 : template dbe::inner::configobject::tref dbe::inner::dbcontroller::create_object_request<
324 : dbe::config_object_aggregates<std::string> >(
325 : dbe::inner::configobject::gref<dbe::config_object_aggregates<std::string> > &,
326 : dbe::inner::configobject::gref<dbe::config_object_aggregates<std::string> >::config_action_notifiable);
327 : //------------------------------------------------------------------------------------------
328 :
329 : //------------------------------------------------------------------------------------------
330 0 : configobject::tref dbcontroller::move_object_request(configobject::tref objref,
331 : std::string const & destfile)
332 : {
333 0 : if (not objref.is_null())
334 : {
335 0 : static_cast<ConfigObject &>(*(objref.refered)).move(destfile);
336 : }
337 :
338 0 : return objref;
339 : }
340 : //------------------------------------------------------------------------------------------
341 :
342 : //------------------------------------------------------------------------------------------
343 0 : configobject::tref dbcontroller::rename_object_request(configobject::tref objref,
344 : std::string const & newname)
345 : {
346 0 : return dbcontroller::ref().rename(objref, newname);
347 : }
348 : //------------------------------------------------------------------------------------------
349 :
350 : //------------------------------------------------------------------------------------------
351 0 : configobject::tref dbcontroller::rename(configobject::tref objref,
352 : std::string const & aname)
353 : {
354 0 : if (not objref.is_null())
355 : {
356 : // pick up the pointer
357 0 : std::shared_ptr<configobject::oref> current_ptr = objref.refered;
358 :
359 : // remove the current reference from the internal map
360 0 : this_allobjects.erase(*current_ptr);
361 0 : try
362 : {
363 : // rename the refered object
364 0 : dbe::config::api::rwdacc::rename_object(static_cast<ConfigObject &>(*current_ptr),
365 : aname);
366 : }
367 0 : catch (dunedaq::conffwk::Generic const & e)
368 : {
369 : // Logging the error but this may not affect program execution per-se
370 0 : FAIL("Object rename failure", dbe::config::errors::parse(e).c_str());
371 0 : }
372 : // position it in its proper place
373 0 : bool nofail;
374 0 : t_object_map::iterator position;
375 0 : std::tie(position, nofail) = this_allobjects.emplace(*current_ptr, current_ptr);
376 :
377 0 : if (not nofail)
378 : {
379 0 : throw daq::dbe::dbcontroller_internal_cache_failure(ERS_HERE);
380 : }
381 0 : return position->second;
382 0 : }
383 0 : return objref;
384 : }
385 : //------------------------------------------------------------------------------------------
386 :
387 : //------------------------------------------------------------------------------------------
388 2 : configobject::tref dbcontroller::get(dbe::cokey const & key)
389 : {
390 2 : return dbcontroller::ref().lookup(key);
391 : }
392 :
393 2 : std::vector<configobject::tref> dbcontroller::gets(std::string const & cname,
394 : std::string const & query)
395 : {
396 2 : std::vector<ConfigObject> database_objects = config::api::rwdacc::query_class(cname,
397 2 : query);
398 2 : std::vector<configobject::tref> result;
399 :
400 8 : for (ConfigObject const & keyin : database_objects)
401 : {
402 6 : try
403 : {
404 12 : result.push_back(dbcontroller::ref().lookup(
405 6 : { keyin.UID(), keyin.class_name() }));
406 : }
407 0 : catch (daq::dbe::config_object_retrieval_result_is_null const & e)
408 : {
409 : // nothing needs be done to specifically handle this case, it just that in some
410 : // cases the underlying database does not contain initialized objects
411 0 : }
412 : }
413 2 : return result;
414 2 : }
415 : //------------------------------------------------------------------------------------------
416 :
417 : //------------------------------------------------------------------------------------------
418 8 : configobject::tref dbcontroller::lookup(dbe::cokey const & key)
419 : {
420 : // Find the object in the database
421 8 : t_object_map::iterator position = this_allobjects.find(key);
422 :
423 8 : if (position == this_allobjects.end())
424 : {
425 : // if it is not in the cache we need to add it
426 5 : ConfigObject toinsert = dbe::config::api::rwdacc::get_object(key.this_class,
427 5 : key.this_name);
428 5 : if (not toinsert.is_null())
429 : {
430 5 : return insert(static_cast<ConfigObject>(toinsert));
431 : }
432 5 : }
433 : else
434 : {
435 3 : return position->second;
436 : }
437 :
438 0 : throw daq::dbe::config_object_retrieval_result_is_null ( ERS_HERE,
439 0 : key.this_name + "@" + key.this_class );
440 : }
441 : //------------------------------------------------------------------------------------------
442 :
443 : //------------------------------------------------------------------------------------------
444 5 : configobject::tref dbcontroller::insert(ConfigObject const & obj)
445 : {
446 : // Construct the oref to add in the internal map
447 5 : std::shared_ptr<configobject::oref> element(new configobject::oref(obj));
448 :
449 5 : bool object_inserted;
450 5 : t_object_map::iterator position;
451 :
452 5 : locker l(this_lock);
453 5 : std::tie(position, object_inserted) = this_allobjects.emplace(*element, element);
454 :
455 5 : if (not object_inserted)
456 : {
457 : // Object is already defined in the database and we replace the old reference with the new.
458 : // A case is if there have been external modification and we try to replay changes
459 0 : static_cast<ConfigObject &>(*position->second) = obj;
460 : }
461 :
462 10 : return position->second;
463 5 : }
464 : //------------------------------------------------------------------------------------------
465 :
466 : //------------------------------------------------------------------------------------------
467 0 : template<typename T> configobject::gref<T> dbcontroller::remove(dbe::tref ref)
468 : {
469 0 : configobject::gref<T> subgraph;
470 :
471 : {
472 0 : locker l(this_lock);
473 : // Record the associated subgraph
474 0 : if (not ref.is_null())
475 : {
476 0 : subgraph.record(ref);
477 : }
478 :
479 : // Need to remove from the internal map all candidates, they will be added at post processing
480 0 : for (T const & key : subgraph.this_remove_stack)
481 : {
482 : // Remove from the internal map
483 0 : this_allobjects.erase({ key.ref.UID(), key.ref.class_name() });
484 : }
485 0 : }
486 :
487 : // Delete the object from the database
488 0 : dbe::config::api::rwdacc::destroy_object(ref.ref());
489 : // Post-process the object recorded subgraph
490 0 : subgraph.post();
491 :
492 0 : return subgraph;
493 0 : }
494 : //------------------------------------------------------------------------------------------
495 :
496 : }
497 : // namespace inner
498 :
499 : template<typename S>
500 0 : inner::configobject::tref config_object_description<S>::ref() const
501 : {
502 0 : if (this_referenced_object.is_null())
503 : {
504 0 : this_referenced_object = dbe::inner::dbcontroller::get(
505 0 : { this->this_name, this->this_class });
506 : }
507 0 : return this_referenced_object;
508 : }
509 :
510 : } // namespace dbe
|