LCOV - code coverage report
Current view: top level - src/libs/tools/src - plugins.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 184 219 84.0 %
Date: 2019-09-12 12:28:41 Functions: 23 25 92.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Implementation of set/get/error plugins
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : 
      11             : #include <helper/keyhelper.hpp>
      12             : #include <plugins.hpp>
      13             : 
      14             : #include <kdbprivate.h>
      15             : 
      16             : #include <algorithm>
      17             : #include <iterator>
      18             : 
      19             : using namespace std;
      20             : 
      21             : namespace kdb
      22             : {
      23             : 
      24             : namespace tools
      25             : {
      26             : 
      27       36144 : Plugins::Plugins () : plugins (NR_OF_PLUGINS), nrStoragePlugins (0), nrResolverPlugins (0)
      28             : {
      29       18072 :         placementInfo["prerollback"] = Place (RESOLVER_PLUGIN, STORAGE_PLUGIN - 1);
      30       18072 :         placementInfo["rollback"] = Place (STORAGE_PLUGIN, STORAGE_PLUGIN);
      31       18072 :         placementInfo["postrollback"] = Place (STORAGE_PLUGIN + 1, NR_OF_PLUGINS - 1);
      32             : 
      33       18072 :         placementInfo["getresolver"] = Place (RESOLVER_PLUGIN, RESOLVER_PLUGIN);
      34       18072 :         placementInfo["pregetstorage"] = Place (RESOLVER_PLUGIN + 1, STORAGE_PLUGIN - 1);
      35       18072 :         placementInfo["getstorage"] = Place (STORAGE_PLUGIN, STORAGE_PLUGIN);
      36       18072 :         placementInfo["postgetstorage"] = Place (STORAGE_PLUGIN + 1, NR_OF_PLUGINS - 1);
      37        4518 :         revPostGet = NR_OF_PLUGINS - 1;
      38             : 
      39       18072 :         placementInfo["setresolver"] = Place (RESOLVER_PLUGIN, RESOLVER_PLUGIN);
      40       18072 :         placementInfo["presetstorage"] = Place (RESOLVER_PLUGIN + 1, STORAGE_PLUGIN - 1);
      41       18072 :         placementInfo["setstorage"] = Place (STORAGE_PLUGIN, STORAGE_PLUGIN);
      42       18072 :         placementInfo["precommit"] = Place (STORAGE_PLUGIN + 1, COMMIT_PLUGIN - 1);
      43       18072 :         placementInfo["commit"] = Place (COMMIT_PLUGIN, COMMIT_PLUGIN);
      44       18072 :         placementInfo["postcommit"] = Place (COMMIT_PLUGIN + 1, NR_OF_PLUGINS - 1);
      45        4518 : }
      46             : 
      47        2309 : void Plugins::addInfo (Plugin & plugin)
      48             : {
      49             :         {
      50        4618 :                 std::string provide;
      51       20781 :                 std::stringstream ss (plugin.lookupInfo ("provides"));
      52       11360 :                 while (ss >> provide)
      53             :                 {
      54        3371 :                         alreadyProvided.push_back (provide);
      55             :                 }
      56             :                 /* Push back the name of the plugin itself */
      57        6927 :                 alreadyProvided.push_back (plugin.name ());
      58             :         }
      59             : 
      60             :         {
      61        4618 :                 std::string need;
      62       20781 :                 std::stringstream ss (plugin.lookupInfo ("needs"));
      63        4868 :                 while (ss >> need)
      64             :                 {
      65         125 :                         needed.push_back (need);
      66             :                 }
      67             :         }
      68             : 
      69             :         {
      70        4618 :                 std::string recommend;
      71       20781 :                 std::stringstream ss (plugin.lookupInfo ("recommends"));
      72        5078 :                 while (ss >> recommend)
      73             :                 {
      74         230 :                         recommended.push_back (recommend);
      75             :                 }
      76             :         }
      77             : 
      78             :         {
      79        4618 :                 std::string conflict;
      80       20781 :                 std::stringstream ss (plugin.lookupInfo ("conflicts"));
      81        4618 :                 while (ss >> conflict)
      82             :                 {
      83           0 :                         alreadyConflict.push_back (conflict);
      84             :                 }
      85             :         }
      86        2309 : }
      87             : 
      88       30017 : void Plugins::addPlugin (Plugin & plugin, std::string which)
      89             : {
      90      294583 :         if (!plugin.findInfo (which, "placements")) return;
      91             : 
      92       46341 :         std::string stacking = plugin.lookupInfo ("stacking");
      93             : 
      94        6119 :         if (which == "postgetstorage" && stacking == "")
      95             :         {
      96         470 :                 plugins[revPostGet--] = &plugin;
      97             :                 return;
      98             :         }
      99             : 
     100       11174 :         plugins[placementInfo[which].current++] = &plugin;
     101             : }
     102             : 
     103             : /**
     104             :  * @brief check if this plugin can be placed in the unfortunately
     105             :  * limited number of slots
     106             :  *
     107             :  * @param plugin the plugin to check
     108             :  * @param which placementInfo it is
     109             :  *
     110             :  * @retval true if it should be added
     111             :  * @retval false no placements (will not be added)
     112             :  */
     113       30028 : bool Plugins::checkPlacement (Plugin & plugin, std::string which)
     114             : {
     115      270252 :         if (!plugin.findInfo (which, "placements")) return false; // nothing to check, won't be added anyway
     116             : 
     117       40762 :         std::string stacking = plugin.lookupInfo ("stacking");
     118             : 
     119        6120 :         if (which == "postgetstorage" && stacking == "")
     120             :         {
     121         940 :                 if (revPostGet >= placementInfo["postgetstorage"].current)
     122             :                 {
     123             :                         return true;
     124             :                 }
     125             : 
     126           0 :                 std::ostringstream os;
     127             :                 os << "Too many plugins!\n"
     128             :                       "The plugin "
     129           0 :                    << plugin.name () << " can't be positioned at position " << which
     130             :                    << " anymore.\n"
     131             :                       "Try to reduce the number of plugins!\n"
     132             :                       "\n"
     133           0 :                       "Failed because of stack overflow: cant place to "
     134           0 :                    << revPostGet << " because " << placementInfo["postgetstorage"].current << " is larger (this slot is in use)." << endl;
     135           0 :                 throw TooManyPlugins (os.str ());
     136             :         }
     137             : 
     138        5588 :         if (placementInfo[which].current > placementInfo[which].max)
     139             :         {
     140           2 :                 std::ostringstream os;
     141             :                 os << "Too many plugins!\n"
     142             :                       "The plugin "
     143           2 :                    << plugin.name () << " can't be positioned at position " << which
     144             :                    << " anymore.\n"
     145             :                       "Try to reduce the number of plugins!\n"
     146             :                       "\n"
     147             :                       "Failed because "
     148          10 :                    << which << " with " << placementInfo[which].current << " is larger than " << placementInfo[which].max << endl;
     149           3 :                 throw TooManyPlugins (os.str ());
     150             :         }
     151             : 
     152             :         return true;
     153             : }
     154             : 
     155          80 : bool Plugins::validateProvided () const
     156             : {
     157         160 :         return getNeededMissing ().empty ();
     158             : }
     159             : 
     160          80 : std::vector<std::string> Plugins::getNeededMissing () const
     161             : {
     162          80 :         std::vector<std::string> ret;
     163         324 :         for (auto & elem : needed)
     164             :         {
     165           8 :                 std::string need = elem;
     166          20 :                 if (std::find (alreadyProvided.begin (), alreadyProvided.end (), need) == alreadyProvided.end ())
     167             :                 {
     168           2 :                         ret.push_back (need);
     169             :                 }
     170             :         }
     171          80 :         return ret;
     172             : }
     173             : 
     174           0 : std::vector<std::string> Plugins::getRecommendedMissing () const
     175             : {
     176           0 :         std::vector<std::string> ret;
     177           0 :         for (auto & elem : recommended)
     178             :         {
     179           0 :                 std::string recommend = elem;
     180           0 :                 if (std::find (alreadyProvided.begin (), alreadyProvided.end (), recommend) == alreadyProvided.end ())
     181             :                 {
     182           0 :                         ret.push_back (recommend);
     183             :                 }
     184             :         }
     185           0 :         return ret;
     186             : }
     187             : 
     188        4064 : void Plugins::checkStorage (Plugin & plugin)
     189             : {
     190       40640 :         if (plugin.findInfo ("storage", "provides"))
     191             :         {
     192        1250 :                 ++nrStoragePlugins;
     193             :         }
     194             : 
     195        4064 :         if (nrStoragePlugins > 1)
     196             :         {
     197           0 :                 --nrStoragePlugins;
     198           0 :                 throw StoragePlugin ();
     199             :         }
     200        4064 : }
     201             : 
     202        4925 : void Plugins::checkResolver (Plugin & plugin)
     203             : {
     204       49250 :         if (plugin.findInfo ("resolver", "provides"))
     205             :         {
     206        2523 :                 ++nrResolverPlugins;
     207             :         }
     208             : 
     209             : 
     210        4925 :         if (nrResolverPlugins > 1)
     211             :         {
     212           0 :                 --nrResolverPlugins;
     213           0 :                 throw ResolverPlugin ();
     214             :         }
     215        4925 : }
     216             : 
     217             : 
     218             : /** Check ordering of plugins.
     219             :  */
     220        2310 : void Plugins::checkOrdering (Plugin & plugin)
     221             : {
     222        4620 :         std::string order;
     223       20790 :         std::stringstream ss (plugin.lookupInfo ("ordering"));
     224        4890 :         while (ss >> order)
     225             :         {
     226             :                 /* Simple look in the already provided names.
     227             :                  * Because both plugin names + provided names are
     228             :                  * there.
     229             :                  * If it is found, we have an ordering violation.
     230             :                  */
     231         675 :                 if (std::find (alreadyProvided.begin (), alreadyProvided.end (), order) != alreadyProvided.end ())
     232             :                 {
     233           0 :                         throw OrderingViolation ();
     234             :                 }
     235             :         }
     236        2310 : }
     237             : 
     238             : /** Check conflicts of plugins.
     239             :  */
     240        2310 : void Plugins::checkConflicts (Plugin & plugin)
     241             : {
     242             :         {
     243        4620 :                 std::string order;
     244       20790 :                 std::stringstream ss (plugin.lookupInfo ("conflicts"));
     245        4620 :                 while (ss >> order)
     246             :                 {
     247             :                         /* Simple look in the already provided names.
     248             :                          * Because both plugin names + provided names are
     249             :                          * there.
     250             :                          * If one is found, we have an conflict.
     251             :                          */
     252           0 :                         if (std::find (alreadyProvided.begin (), alreadyProvided.end (), order) != alreadyProvided.end ())
     253             :                         {
     254           0 :                                 throw ConflictViolation ();
     255             :                         }
     256             :                 }
     257             :         }
     258             : 
     259             :         /* Is there a conflict against the name? */
     260       13860 :         if (std::find (alreadyConflict.begin (), alreadyConflict.end (), plugin.name ()) != alreadyConflict.end ())
     261             :         {
     262           0 :                 throw ConflictViolation ();
     263             :         }
     264             : 
     265             :         /* Is there a conflict against what it provides? */
     266        4620 :         std::string order;
     267       20790 :         std::stringstream ss (plugin.lookupInfo ("provides"));
     268       11364 :         while (ss >> order)
     269             :         {
     270       16860 :                 if (std::find (alreadyConflict.begin (), alreadyConflict.end (), order) != alreadyConflict.end ())
     271             :                 {
     272           0 :                         throw ConflictViolation ();
     273             :                 }
     274             :         }
     275        2310 : }
     276             : 
     277             : 
     278        2310 : void ErrorPlugins::tryPlugin (Plugin & plugin)
     279             : {
     280        2310 :         checkOrdering (plugin);
     281        2310 :         checkConflicts (plugin);
     282             : 
     283        2310 :         bool willBeAdded = false;
     284        9240 :         willBeAdded |= checkPlacement (plugin, "prerollback");
     285        9240 :         willBeAdded |= checkPlacement (plugin, "rollback");
     286        9240 :         willBeAdded |= checkPlacement (plugin, "postrollback");
     287        2310 :         if (!willBeAdded) return;
     288             : 
     289        3444 :         if (!plugin.getSymbol ("error"))
     290             :         {
     291           0 :                 throw MissingSymbol ("error");
     292             :         }
     293             : 
     294         861 :         checkResolver (plugin);
     295             : }
     296             : 
     297             : 
     298        2310 : void GetPlugins::tryPlugin (Plugin & plugin)
     299             : {
     300        2310 :         bool willBeAdded = false;
     301        9240 :         willBeAdded |= checkPlacement (plugin, "getresolver");
     302        9240 :         willBeAdded |= checkPlacement (plugin, "pregetstorage");
     303        9240 :         willBeAdded |= checkPlacement (plugin, "getstorage");
     304        9240 :         willBeAdded |= checkPlacement (plugin, "postgetstorage");
     305        2310 :         if (!willBeAdded) return;
     306             : 
     307        7116 :         if (!plugin.getSymbol ("get"))
     308             :         {
     309           0 :                 throw MissingSymbol ("get");
     310             :         }
     311             : 
     312        1779 :         checkStorage (plugin);
     313        1779 :         checkResolver (plugin);
     314             : }
     315             : 
     316        2310 : void SetPlugins::tryPlugin (Plugin & plugin)
     317             : {
     318        2310 :         bool willBeAdded = false;
     319        9240 :         willBeAdded |= checkPlacement (plugin, "setresolver");
     320        9240 :         willBeAdded |= checkPlacement (plugin, "presetstorage");
     321        9240 :         willBeAdded |= checkPlacement (plugin, "setstorage");
     322        9239 :         willBeAdded |= checkPlacement (plugin, "precommit");
     323        9236 :         willBeAdded |= checkPlacement (plugin, "commit");
     324        9236 :         willBeAdded |= checkPlacement (plugin, "postcommit");
     325        2309 :         if (!willBeAdded) return;
     326             : 
     327        9140 :         if (!plugin.getSymbol ("set"))
     328             :         {
     329           0 :                 throw MissingSymbol ("set");
     330             :         }
     331             : 
     332             : 
     333        2285 :         checkStorage (plugin);
     334        2285 :         checkResolver (plugin);
     335             : }
     336             : 
     337             : 
     338        2309 : void ErrorPlugins::addPlugin (Plugin & plugin)
     339             : {
     340        9236 :         Plugins::addPlugin (plugin, "prerollback");
     341        9236 :         Plugins::addPlugin (plugin, "rollback");
     342        9236 :         Plugins::addPlugin (plugin, "postrollback");
     343             : 
     344        2309 :         Plugins::addInfo (plugin);
     345        2309 : }
     346             : 
     347        2309 : void GetPlugins::addPlugin (Plugin & plugin)
     348             : {
     349        9236 :         Plugins::addPlugin (plugin, "getresolver");
     350        9236 :         Plugins::addPlugin (plugin, "pregetstorage");
     351        9236 :         Plugins::addPlugin (plugin, "getstorage");
     352        9236 :         Plugins::addPlugin (plugin, "postgetstorage");
     353        2309 : }
     354             : 
     355        2309 : void SetPlugins::addPlugin (Plugin & plugin)
     356             : {
     357        9236 :         Plugins::addPlugin (plugin, "setresolver");
     358        9236 :         Plugins::addPlugin (plugin, "presetstorage");
     359        9236 :         Plugins::addPlugin (plugin, "setstorage");
     360        9236 :         Plugins::addPlugin (plugin, "precommit");
     361        9236 :         Plugins::addPlugin (plugin, "commit");
     362        9236 :         Plugins::addPlugin (plugin, "postcommit");
     363        2309 : }
     364             : 
     365             : 
     366           0 : void ErrorPlugins::status (std::ostream & os) const
     367             : {
     368           0 :         std::vector<std::string> n = getNeededMissing ();
     369           0 :         if (!n.empty ())
     370             :         {
     371           0 :                 os << "Needed plugins that are missing are: ";
     372           0 :                 std::copy (n.begin (), n.end (), std::ostream_iterator<std::string> (os, " "));
     373             :                 os << std::endl;
     374             :         }
     375           0 :         std::vector<std::string> r = getRecommendedMissing ();
     376           0 :         if (!r.empty ())
     377             :         {
     378           0 :                 os << "Recommendations that are not fulfilled are: ";
     379           0 :                 std::copy (r.begin (), r.end (), std::ostream_iterator<std::string> (os, " "));
     380             :                 os << std::endl;
     381             :         }
     382           0 : }
     383             : 
     384             : 
     385          84 : bool ErrorPlugins::validated () const
     386             : {
     387          84 :         return nrResolverPlugins == 1 && validateProvided ();
     388             : }
     389             : 
     390          84 : bool GetPlugins::validated () const
     391             : {
     392          84 :         return nrStoragePlugins == 1 && nrResolverPlugins == 1;
     393             : }
     394             : 
     395          84 : bool SetPlugins::validated () const
     396             : {
     397          84 :         return nrStoragePlugins == 1 && nrResolverPlugins == 1;
     398             : }
     399             : 
     400             : 
     401             : namespace
     402             : {
     403        1616 : void serializeConfig (std::string name, KeySet const & ks, KeySet & ret)
     404             : {
     405        3203 :         if (!ks.size ()) return;
     406             : 
     407          58 :         Key oldParent ("user", KEY_END);
     408          87 :         Key newParent (name + "/config", KEY_END);
     409             : 
     410          29 :         ret.append (newParent);
     411             : 
     412         177 :         for (KeySet::iterator i = ks.begin (); i != ks.end (); ++i)
     413             :         {
     414         225 :                 Key k (i->dup ());
     415         225 :                 if (k.getNamespace () == "user") ret.append (kdb::tools::helper::rebaseKey (k, oldParent, newParent));
     416             :         }
     417             : }
     418             : } // namespace
     419             : 
     420             : 
     421         599 : void ErrorPlugins::serialise (Key & baseKey, KeySet & ret)
     422             : {
     423        4792 :         ret.append (*Key (baseKey.getName () + "/errorplugins", KEY_COMMENT, "List of plugins to use", KEY_END));
     424             : 
     425        6589 :         for (int i = 0; i < NR_OF_PLUGINS; ++i)
     426             :         {
     427       17464 :                 if (plugins[i] == nullptr) continue;
     428         506 :                 bool fr = plugins[i]->firstRef;
     429             : 
     430        1012 :                 std::ostringstream pluginNumber;
     431         506 :                 pluginNumber << i;
     432        4554 :                 std::string name = baseKey.getName () + "/errorplugins/#" + pluginNumber.str () + plugins[i]->refname ();
     433        3542 :                 ret.append (*Key (name, KEY_COMMENT, "A plugin", KEY_END));
     434        2530 :                 if (fr) serializeConfig (name, plugins[i]->getConfig (), ret);
     435             :         }
     436         599 : }
     437             : 
     438         599 : void GetPlugins::serialise (Key & baseKey, KeySet & ret)
     439             : {
     440        4792 :         ret.append (*Key (baseKey.getName () + "/getplugins", KEY_COMMENT, "List of plugins to use", KEY_END));
     441             : 
     442        6589 :         for (int i = 0; i < NR_OF_PLUGINS; ++i)
     443             :         {
     444       16860 :                 if (plugins[i] == nullptr) continue;
     445        1110 :                 bool fr = plugins[i]->firstRef;
     446             : 
     447        2220 :                 std::ostringstream pluginNumber;
     448        1110 :                 pluginNumber << i;
     449        9990 :                 std::string name = baseKey.getName () + "/getplugins/#" + pluginNumber.str () + plugins[i]->refname ();
     450        7770 :                 ret.append (*Key (name, KEY_COMMENT, "A plugin", KEY_END));
     451        3518 :                 if (fr) serializeConfig (name, plugins[i]->getConfig (), ret);
     452             :         }
     453         599 : }
     454             : 
     455             : 
     456         599 : void SetPlugins::serialise (Key & baseKey, KeySet & ret)
     457             : {
     458        4792 :         ret.append (*Key (baseKey.getName () + "/setplugins", KEY_COMMENT, "List of plugins to use", KEY_END));
     459             : 
     460        6589 :         for (int i = 0; i < NR_OF_PLUGINS; ++i)
     461             :         {
     462       15871 :                 if (plugins[i] == nullptr) continue;
     463        2099 :                 bool fr = plugins[i]->firstRef;
     464             : 
     465        4198 :                 std::ostringstream pluginNumber;
     466        2099 :                 pluginNumber << i;
     467       18891 :                 std::string name = baseKey.getName () + "/setplugins/#" + pluginNumber.str () + plugins[i]->refname ();
     468       14693 :                 ret.append (*Key (name, KEY_COMMENT, "A plugin", KEY_END));
     469        4131 :                 if (fr) serializeConfig (name, plugins[i]->getConfig (), ret);
     470             :         }
     471         599 : }
     472             : } // namespace tools
     473             : } // namespace kdb

Generated by: LCOV version 1.13