LCOV - code coverage report
Current view: top level - dbe/src/internal - dbcontroller.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 21.2 % 170 36
Test Date: 2026-10-11 15:05:20 Functions: 30.4 % 23 7

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

Generated by: LCOV version 2.0-1