LCOV - code coverage report
Current view: top level - dbe/src/internal - dbcontroller.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 21.3 % 183 39
Test Date: 2025-12-21 13:07:08 Functions: 30.4 % 23 7

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

Generated by: LCOV version 2.0-1