LCOV - code coverage report
Current view: top level - src/libs/tools/src - backend.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 228 304 75.0 %
Date: 2019-09-12 12:28:41 Functions: 20 30 66.7 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Implementation of backend
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : 
      11             : #include <backend.hpp>
      12             : #include <backends.hpp>
      13             : 
      14             : 
      15             : #include <helper/keyhelper.hpp>
      16             : #include <kdbmodule.h>
      17             : #include <kdbplugin.h>
      18             : #include <kdbprivate.h>
      19             : 
      20             : #include <kdbease.h> // for ckdb::elektraArrayIncName
      21             : 
      22             : #include <algorithm>
      23             : 
      24             : #include <cassert>
      25             : #include <kdb.hpp>
      26             : 
      27             : 
      28             : using namespace std;
      29             : 
      30             : 
      31             : namespace kdb
      32             : {
      33             : 
      34             : 
      35             : namespace tools
      36             : {
      37             : 
      38        2523 : BackendInterface::~BackendInterface ()
      39             : {
      40        2523 : }
      41             : 
      42        1983 : MountBackendInterface::~MountBackendInterface ()
      43             : {
      44        1983 : }
      45             : 
      46        1985 : SerializeInterface::~SerializeInterface ()
      47             : {
      48        1985 : }
      49             : 
      50             : /** Creates a new empty backend.
      51             :  *
      52             :  * */
      53       13554 : Backend::Backend () : plugins ()
      54             : {
      55        1506 : }
      56             : 
      57             : 
      58       11394 : Backend::~Backend ()
      59             : {
      60        2358 : }
      61             : 
      62           0 : Backend::Backend (Backend && other)
      63             : : getplugins (other.getplugins), setplugins (other.setplugins), errorplugins (other.errorplugins), mp (other.mp),
      64           0 :   configFile (other.configFile), modules (other.modules), config (other.config), plugins (std::move (other.plugins))
      65             : {
      66           0 : }
      67             : 
      68           0 : Backend & Backend::operator= (Backend && other)
      69             : {
      70           0 :         plugins = std::move (other.plugins);
      71           0 :         getplugins = other.getplugins;
      72           0 :         setplugins = other.setplugins;
      73           0 :         errorplugins = other.errorplugins;
      74           0 :         mp = other.mp;
      75           0 :         configFile = other.configFile;
      76           0 :         modules = other.modules;
      77           0 :         config = other.config;
      78           0 :         return *this;
      79             : }
      80             : 
      81             : /**
      82             :  * @brief Sets the mountpoint for the backend
      83             :  *
      84             :  * @throw MountpointInvalidException
      85             :  * @throw MountpointAlreadyInUseException
      86             :  *
      87             :  * @param mountpoint the key name will be used as mountpoint.
      88             :  *    It is allowed to pass a key with a KEY_CASCADING_NAME
      89             :  *
      90             :  * @param mountConf needs to include the keys below
      91             :  * system/elektra/mountpoints
      92             :  */
      93        1036 : void Backend::setMountpoint (Key mountpoint, KeySet mountConf)
      94             : {
      95        3108 :         Backends::BackendInfoVector info = Backends::getBackendInfo (mountConf);
      96        2072 :         std::string namesAsString;
      97        2072 :         std::vector<std::string> alreadyUsedMountpoints;
      98        4480 :         for (Backends::BackendInfoVector::const_iterator it = info.begin (); it != info.end (); ++it)
      99             :         {
     100         168 :                 std::string const & name = it->mountpoint;
     101         168 :                 if (name == "/")
     102             :                 {
     103          90 :                         alreadyUsedMountpoints.push_back ("spec");
     104          90 :                         alreadyUsedMountpoints.push_back ("dir");
     105          90 :                         alreadyUsedMountpoints.push_back ("user");
     106          90 :                         alreadyUsedMountpoints.push_back ("system");
     107             :                 }
     108         150 :                 else if (name.at (0) == '/')
     109             :                 {
     110         330 :                         alreadyUsedMountpoints.push_back (Key ("dir" + name, KEY_END).getName ());
     111         330 :                         alreadyUsedMountpoints.push_back (Key ("user" + name, KEY_END).getName ());
     112         330 :                         alreadyUsedMountpoints.push_back (Key ("system" + name, KEY_END).getName ());
     113             :                 }
     114             : 
     115             :                 // always add name itself, too
     116         168 :                 alreadyUsedMountpoints.push_back (name);
     117             : 
     118         168 :                 namesAsString += name;
     119         168 :                 namesAsString += " ";
     120             :         }
     121             : 
     122             :         // STEP 0: check for null key
     123        1036 :         if (!mountpoint)
     124             :         {
     125           8 :                 throw MountpointAlreadyInUseException ("Null mountpoint not allowed");
     126             :         }
     127             : 
     128        2068 :         std::string smp = mountpoint.getName ();
     129             : 
     130             :         // STEP 1: check for empty name
     131        1034 :         if (smp.empty ())
     132             :         {
     133          24 :                 throw MountpointAlreadyInUseException ("Empty mountpoint not allowed");
     134             :         }
     135             : 
     136             :         // STEP 2: check for wrong namespace (proc)
     137        3084 :         if (mountpoint.getNamespace () == "proc")
     138             :         {
     139          30 :                 throw MountpointAlreadyInUseException ("proc mountpoint not allowed");
     140             :         }
     141             : 
     142             :         // STEP 3: check for name match
     143        1018 :         if (smp == "/")
     144             :         {
     145         128 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), "/") != alreadyUsedMountpoints.end ())
     146             :                 {
     147             :                         throw MountpointAlreadyInUseException (
     148           8 :                                 "Root mountpoint not possible, because the root mountpoint already exists.\n");
     149             :                 }
     150          60 :                 Key specmp ("spec", KEY_END);
     151         150 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), specmp.getName ()) !=
     152          30 :                     alreadyUsedMountpoints.end ())
     153             :                 {
     154           0 :                         throw MountpointAlreadyInUseException ("Root mountpoint not possible, because spec mountpoint already exists.\n");
     155             :                 }
     156          60 :                 Key dkmp ("dir", KEY_END);
     157         150 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), dkmp.getName ()) !=
     158          30 :                     alreadyUsedMountpoints.end ())
     159             :                 {
     160           0 :                         throw MountpointAlreadyInUseException ("Root mountpoint not possible, because dir mountpoint already exists.\n");
     161             :                 }
     162          60 :                 Key ukmp ("user", KEY_END);
     163         150 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), ukmp.getName ()) !=
     164          30 :                     alreadyUsedMountpoints.end ())
     165             :                 {
     166           0 :                         throw MountpointAlreadyInUseException ("Root mountpoint not possible, because user mountpoint already exists.\n");
     167             :                 }
     168          60 :                 Key skmp ("system", KEY_END);
     169         150 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), skmp.getName ()) !=
     170          30 :                     alreadyUsedMountpoints.end ())
     171             :                 {
     172           0 :                         throw MountpointAlreadyInUseException ("Root mountpoint not possible, because system mountpoint already exists.\n");
     173             :                 }
     174             :         }
     175         986 :         else if (smp.at (0) == '/')
     176             :         {
     177        1204 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), smp) != alreadyUsedMountpoints.end ())
     178             :                 {
     179           3 :                         throw MountpointAlreadyInUseException ("Cascading mountpoint " + smp +
     180           5 :                                                                " not possible, because cascading mountpoint " + smp + " already exists.\n");
     181             :                 }
     182         900 :                 Key dkmp ("dir" + smp, KEY_END);
     183        1500 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), dkmp.getName ()) !=
     184         300 :                     alreadyUsedMountpoints.end ())
     185             :                 {
     186          12 :                         throw MountpointAlreadyInUseException ("Cascading mountpoint " + smp +
     187          12 :                                                                " not possible, because dir mountpoint already exists.\n");
     188             :                 }
     189         888 :                 Key ukmp ("user" + smp, KEY_END);
     190        1480 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), ukmp.getName ()) !=
     191         296 :                     alreadyUsedMountpoints.end ())
     192             :                 {
     193          12 :                         throw MountpointAlreadyInUseException ("Cascading mountpoint " + smp +
     194          12 :                                                                " not possible, because user mountpoint already exists.\n");
     195             :                 }
     196         876 :                 Key skmp ("system" + smp, KEY_END);
     197        1460 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), skmp.getName ()) !=
     198         292 :                     alreadyUsedMountpoints.end ())
     199             :                 {
     200          12 :                         throw MountpointAlreadyInUseException ("Cascading mountpoint " + smp +
     201          12 :                                                                " not possible, because system mountpoint already exists.\n");
     202             :                 }
     203             :         }
     204             :         else
     205             :         {
     206        2055 :                 Key kmp (smp, KEY_END);
     207         685 :                 if (!kmp.isValid ()) throw MountpointInvalidException ();
     208        3425 :                 if (std::find (alreadyUsedMountpoints.begin (), alreadyUsedMountpoints.end (), kmp.getName ()) !=
     209         685 :                     alreadyUsedMountpoints.end ())
     210             :                 {
     211         270 :                         throw MountpointAlreadyInUseException (std::string ("Mountpoint ") + smp +
     212         180 :                                                                " is one of the already used names: " + namesAsString);
     213             :                 }
     214             :         }
     215             : 
     216             :         // TODO STEP 4: check if mounted below system/elektra
     217        2874 :         Key elektraCheck (mountpoint.dup ());
     218         958 :         helper::removeNamespace (elektraCheck);
     219        2874 :         if (elektraCheck.isBelowOrSame (Key ("/elektra", KEY_END)))
     220             :         {
     221             :                 throw MountpointAlreadyInUseException (
     222         204 :                         std::string ("Mountpoint ") + smp +
     223         102 :                         " is below the reserved names /elektra because it would cause inconsistencies in this or future versions");
     224             :         }
     225             : 
     226             :         // everything worked, swap it
     227        1848 :         std::swap (this->mp, smp);
     228         924 : }
     229             : 
     230             : /**
     231             :  * @brief Backend Config to add to
     232             :  *
     233             :  * @param ks the config to add, should be below system/
     234             :  */
     235         245 : void Backend::setBackendConfig (KeySet const & ks)
     236             : {
     237         490 :         config.append (ks);
     238         245 : }
     239             : 
     240             : 
     241             : /**@pre: resolver needs to be loaded first
     242             :  * Will check the filename and use it as configFile for this backend.
     243             :  * @throw FileNotValidException if filename is not valid
     244             :  * @throw MissingSymbol if plugin does not implement 'checkfile' */
     245         730 : void Backend::useConfigFile (std::string file)
     246             : {
     247             :         typedef int (*checkFilePtr) (const char *);
     248         730 :         checkFilePtr checkFileFunction = nullptr;
     249             : 
     250        2926 :         for (auto & elem : plugins)
     251             :         {
     252             :                 try
     253             :                 {
     254        3680 :                         checkFileFunction = reinterpret_cast<checkFilePtr> (elem->getSymbol ("checkfile"));
     255         730 :                         break;
     256             :                 }
     257           6 :                 catch (MissingSymbol const & ms)
     258             :                 {
     259             :                 }
     260             :         }
     261             : 
     262         730 :         if (!checkFileFunction)
     263             :         {
     264           0 :                 throw MissingSymbol ("No resolver with checkfile found");
     265             :         }
     266             : 
     267             : 
     268         730 :         int res = checkFileFunction (file.c_str ());
     269             : 
     270         730 :         if (res == -1) throw FileNotValidException ();
     271             : 
     272        1460 :         configFile = file;
     273         730 : }
     274             : 
     275             : 
     276        2318 : void Backend::tryPlugin (PluginSpec const & spec)
     277             : {
     278        4628 :         PluginPtr plugin = modules.load (spec);
     279             : 
     280        2310 :         errorplugins.tryPlugin (*plugin.get ());
     281        2310 :         getplugins.tryPlugin (*plugin.get ());
     282        2310 :         setplugins.tryPlugin (*plugin.get ());
     283             : 
     284             : 
     285       11470 :         for (auto & elem : plugins)
     286             :         {
     287        8936 :                 if (plugin->getFullName () == elem->getFullName ()) throw PluginAlreadyInserted (plugin->getFullName ());
     288             :         }
     289             : 
     290             : 
     291        4618 :         plugins.push_back (std::move (plugin));
     292        2309 : }
     293             : 
     294             : 
     295             : /**
     296             :  * Add a plugin that can be loaded, meets all
     297             :  * constraints.
     298             :  *
     299             :  * @note that this does not mean that the backend
     300             :  * validates after it is added. It only means that
     301             :  * the situation is not getting worse.
     302             :  *
     303             :  * @throw PluginCheckException or its subclasses if it was not possible
     304             :  * to load the plugin
     305             :  *
     306             :  * For validation @see validated().
     307             :  */
     308        2318 : void Backend::addPlugin (PluginSpec const & plugin)
     309             : {
     310        4636 :         KeySet fullPluginConfig = plugin.getConfig ();
     311        6954 :         fullPluginConfig.append (plugin.getConfig ()); // add previous configs
     312        2318 :         tryPlugin (plugin);
     313        6927 :         errorplugins.addPlugin (*plugins.back ());
     314        6927 :         getplugins.addPlugin (*plugins.back ());
     315        6927 :         setplugins.addPlugin (*plugins.back ());
     316             : 
     317        9236 :         KeySet toAdd = plugins.back ()->getNeededConfig ();
     318        4618 :         config.append (toAdd);
     319        2309 : }
     320             : 
     321             : 
     322             : /**
     323             :  * @return true if backend is validated
     324             :  * @return false if more plugins are needed to be valided
     325             :  */
     326          84 : bool Backend::validated () const
     327             : {
     328          84 :         bool ret = true;
     329             : 
     330             : 
     331          84 :         if (!errorplugins.validated ()) ret = false;
     332          84 :         if (!getplugins.validated ()) ret = false;
     333          84 :         if (!setplugins.validated ()) ret = false;
     334             : 
     335             : 
     336          84 :         return ret;
     337             : }
     338             : 
     339           0 : void Backend::status (std::ostream & os) const
     340             : {
     341           0 :         if (validated ())
     342             :         {
     343           0 :                 os << "No error, everything validated" << std::endl;
     344             :         }
     345             :         else
     346             :         {
     347           0 :                 os << "Backend is not validated" << std::endl;
     348           0 :                 if (!errorplugins.validated ())
     349             :                 {
     350           0 :                         os << "Error Plugins are not validated" << std::endl;
     351             :                 }
     352             : 
     353           0 :                 if (!getplugins.validated ())
     354             :                 {
     355           0 :                         os << "Get Plugins are not validated" << std::endl;
     356             :                 }
     357             : 
     358           0 :                 if (!setplugins.validated ())
     359             :                 {
     360           0 :                         os << "Set Plugins are not validated" << std::endl;
     361             :                 }
     362             :         }
     363           0 :         errorplugins.status (os);
     364           0 : }
     365             : 
     366             : /**
     367             :  * @brief Prints the current status
     368             :  *
     369             :  * @param os stream to print to
     370             :  * @param b backend to get status from
     371             :  *
     372             :  * @return ref to stream
     373             :  */
     374           0 : std::ostream & operator<< (std::ostream & os, Backend const & b)
     375             : {
     376           0 :         b.status (os);
     377           0 :         return os;
     378             : }
     379             : 
     380             : 
     381             : /**
     382             :  * @pre name and mountpoint set
     383             :  * Add plugin serialization into keyset ret.
     384             :  *
     385             :  * Only can be done once!
     386             :  * (see firstRef in Plugin)
     387             :  * */
     388         599 : void Backend::serialize (kdb::KeySet & ret)
     389             : {
     390             :         assert (!mp.empty ());
     391        1198 :         Key backendRootKey (Backends::mountpointsPath, KEY_END);
     392         599 :         backendRootKey.addBaseName (mp);
     393        2995 :         backendRootKey.setString ("This is a configuration for a backend, see subkeys for more information");
     394         599 :         ret.append (backendRootKey);
     395             : 
     396             : 
     397        1198 :         if (mp == "/")
     398             :         {
     399         168 :                 ret.append (*Key (backendRootKey.getName () + "/mountpoint", KEY_VALUE, "/", KEY_COMMENT,
     400             :                                   "The mount point stores the location where the backend should be mounted.\n"
     401             :                                   "This is the root mountpoint.\n",
     402          24 :                                   KEY_END));
     403             :         }
     404        1150 :         else if (mp.at (0) == '/')
     405             :         {
     406        1584 :                 ret.append (*Key (backendRootKey.getName () + "/mountpoint", KEY_VALUE, mp.c_str (), KEY_COMMENT,
     407             :                                   "The mount point stores the location where the backend should be mounted.\n"
     408             :                                   "This is a cascading mountpoint.\n"
     409             :                                   "That means it is both mounted to dir, user and system.",
     410         198 :                                   KEY_END));
     411             :         }
     412             :         else
     413             :         {
     414        3016 :                 ret.append (*Key (backendRootKey.getName () + "/mountpoint", KEY_VALUE, mp.c_str (), KEY_COMMENT,
     415             :                                   "The mount point stores the location where the backend should be mounted.\n"
     416             :                                   "This is a normal mount point.\n",
     417         377 :                                   KEY_END));
     418             :         }
     419             : 
     420        2995 :         const string configBasePath = Backends::getBasePath (mp) + "/config";
     421        2396 :         ret.append (Key (configBasePath, KEY_END));
     422             : 
     423        1198 :         config.rewind ();
     424        1797 :         Key common = config.next ();
     425        1198 :         Key oldParent ("system", KEY_END);
     426        1797 :         Key newParent (configBasePath, KEY_END);
     427             : 
     428        3360 :         for (KeySet::iterator i = config.begin (); i != config.end (); ++i)
     429             :         {
     430        2410 :                 Key k (i->dup ());
     431        1446 :                 ret.append (kdb::tools::helper::rebaseKey (k, oldParent, newParent));
     432             :         }
     433             : 
     434             : 
     435         599 :         errorplugins.serialise (backendRootKey, ret);
     436         599 :         getplugins.serialise (backendRootKey, ret);
     437         599 :         setplugins.serialise (backendRootKey, ret);
     438             : 
     439        4792 :         ret.append (*Key (backendRootKey.getName () + "/config/path", KEY_VALUE, configFile.c_str (), KEY_COMMENT,
     440         599 :                           "The path for this backend. Note that plugins can override that with more specific configuration.", KEY_END));
     441         599 : }
     442             : 
     443           4 : void PluginAdder::addPlugin (PluginSpec const & spec)
     444             : {
     445           8 :         PluginPtr plugin = modules.load (spec);
     446           4 :         if (!plugin)
     447             :         {
     448           0 :                 throw NoPlugin (spec.getName ());
     449             :         }
     450          12 :         std::shared_ptr<Plugin> sharedPlugin = std::move (plugin);
     451             : 
     452          36 :         std::istringstream ss (sharedPlugin->lookupInfo ("placements"));
     453           4 :         std::string placement;
     454          36 :         while (ss >> placement)
     455             :         {
     456         140 :                 if (sharedPlugin->lookupInfo ("stacking") == "" && placement == "postgetstorage")
     457             :                 {
     458             :                         // reverse postgetstorage, except stacking is set
     459           8 :                         plugins[placement].push_front (sharedPlugin);
     460             :                 }
     461             :                 else
     462             :                 {
     463          20 :                         plugins[placement].push_back (sharedPlugin);
     464             :                 }
     465             :         }
     466           4 : }
     467             : 
     468             : namespace
     469             : {
     470         182 : void append (std::string placement, std::string & where, std::string checkPlacement)
     471             : {
     472         182 :         if (placement == checkPlacement)
     473             :         {
     474          13 :                 if (where.empty ())
     475             :                 {
     476             :                         where = placement;
     477             :                 }
     478             :                 else
     479             :                 {
     480           4 :                         where += " ";
     481             :                         where += placement;
     482             :                 }
     483             :         }
     484         182 : }
     485             : } // namespace
     486             : 
     487          32 : struct Placements
     488             : {
     489             :         std::string get;
     490             :         std::string set;
     491             :         std::string error;
     492             : 
     493          14 :         void addPlacement (std::string placement)
     494             :         {
     495          84 :                 append (placement, error, "prerollback");
     496          84 :                 append (placement, error, "rollback");
     497          84 :                 append (placement, error, "postrollback");
     498             : 
     499          84 :                 append (placement, get, "getresolver");
     500          84 :                 append (placement, get, "pregetstorage");
     501          84 :                 append (placement, get, "getstorage");
     502          84 :                 append (placement, get, "postgetstorage");
     503             : 
     504          84 :                 append (placement, set, "setresolver");
     505          84 :                 append (placement, set, "presetstorage");
     506          84 :                 append (placement, set, "setstorage");
     507          84 :                 append (placement, set, "precommit");
     508          84 :                 append (placement, set, "commit");
     509          84 :                 append (placement, set, "postcommit");
     510          14 :         }
     511             : };
     512             : 
     513             : namespace
     514             : {
     515          12 : Key g (Key placements, std::string name, std::string value)
     516             : {
     517          24 :         Key x (placements.dup ());
     518          12 :         x.addBaseName (name);
     519          36 :         x.setString (value);
     520          12 :         return x;
     521             : }
     522             : 
     523           4 : void serializeConf (kdb::KeySet & ret, Key config, KeySet const & pluginConfig)
     524             : {
     525           4 :         if (pluginConfig.size () != 0)
     526             :         {
     527           0 :                 ret.append (config);
     528           0 :                 for (auto const & key : pluginConfig)
     529             :                 {
     530           0 :                         Key k (key.dup ());
     531           0 :                         helper::removeNamespace (k);
     532           0 :                         ret.append (Key (config.getName () + k.getName (), KEY_VALUE, key.getString ().c_str (), KEY_END));
     533             :                 }
     534             :         }
     535           4 : }
     536             : } // namespace
     537             : 
     538           2 : void GlobalPlugins::serialize (kdb::KeySet & ret)
     539             : {
     540             :         // transform to suitable data structure
     541           4 :         std::map<std::shared_ptr<Plugin>, Placements> pp;
     542          16 :         for (auto const & placements : plugins)
     543             :         {
     544          44 :                 for (auto const & plugin : placements.second)
     545             :                 {
     546         126 :                         std::istringstream ss (plugin->lookupInfo ("status"));
     547          28 :                         std::string status;
     548          14 :                         bool isglobal = false;
     549         184 :                         while (ss >> status)
     550             :                         {
     551          78 :                                 if (status == "global") isglobal = true;
     552             :                         }
     553             : 
     554          14 :                         if (!isglobal)
     555             :                         {
     556           0 :                                 throw NoGlobalPlugin (plugin->name ());
     557             :                         }
     558             : 
     559          42 :                         pp[plugin].addPlacement (placements.first);
     560             :                 }
     561             :         }
     562             : 
     563           6 :         ret.append (Key ("system/elektra/globalplugins", KEY_VALUE, "", KEY_END));
     564           6 :         ret.append (Key ("system/elektra/globalplugins/postcommit", KEY_VALUE, "list", KEY_END));
     565           6 :         ret.append (Key ("system/elektra/globalplugins/postcommit/user", KEY_VALUE, "list", KEY_END));
     566           6 :         ret.append (Key ("system/elektra/globalplugins/postcommit/user/placements", KEY_VALUE, "", KEY_END));
     567           4 :         ret.append (Key ("system/elektra/globalplugins/postcommit/user/placements/set", KEY_VALUE, "presetstorage precommit postcommit",
     568           2 :                          KEY_END));
     569             :         ret.append (
     570           6 :                 Key ("system/elektra/globalplugins/postcommit/user/placements/get", KEY_VALUE, "pregetstorage postgetstorage", KEY_END));
     571           6 :         ret.append (Key ("system/elektra/globalplugins/postcommit/user/placements/error", KEY_VALUE, "prerollback postrollback", KEY_END));
     572           6 :         ret.append (Key ("system/elektra/globalplugins/postcommit/user/plugins", KEY_VALUE, "", KEY_END));
     573           4 :         Key i ("system/elektra/globalplugins/postcommit/user/plugins/#0", KEY_END);
     574          10 :         for (auto const & plugin : pp)
     575             :         {
     576          12 :                 i.setString (plugin.first->name ());
     577          16 :                 ret.append (i.dup ());
     578          12 :                 Key placements (i.dup ());
     579          16 :                 placements.addBaseName ("placements");
     580           4 :                 ret.append (placements);
     581             : 
     582          40 :                 ret.append (g (placements, "get", plugin.second.get));
     583          40 :                 ret.append (g (placements, "set", plugin.second.set));
     584          40 :                 ret.append (g (placements, "error", plugin.second.error));
     585             : 
     586          20 :                 serializeConf (ret, Key (i.getName () + "/config", KEY_VALUE, "", KEY_END), plugin.first->getConfig ());
     587           4 :                 ckdb::elektraArrayIncName (*i);
     588             :         }
     589           6 :         ret.append (Key ("system/elektra/globalplugins/postrollback", KEY_VALUE, "list", KEY_END));
     590           6 :         ret.append (Key ("system/elektra/globalplugins/precommit", KEY_VALUE, "list", KEY_END));
     591           6 :         ret.append (Key ("system/elektra/globalplugins/pregetstorage", KEY_VALUE, "list", KEY_END));
     592           6 :         ret.append (Key ("system/elektra/globalplugins/postgetstorage", KEY_VALUE, "list", KEY_END));
     593           6 :         ret.append (Key ("system/elektra/globalplugins/presetstorage", KEY_VALUE, "list", KEY_END));
     594           6 :         ret.append (Key ("system/elektra/globalplugins/prerollback", KEY_VALUE, "list", KEY_END));
     595           2 : }
     596             : 
     597           0 : void ImportExportBackend::status (std::ostream & os) const
     598             : {
     599           0 :         if (plugins.empty ())
     600           0 :                 os << "no plugin added" << std::endl;
     601           0 :         else if (plugins.find ("setstorage") == plugins.end ())
     602           0 :                 os << "no storage plugin added" << std::endl;
     603             :         else
     604           0 :                 os << "everything ok" << std::endl;
     605           0 : }
     606             : 
     607           0 : void ImportExportBackend::importFromFile (KeySet & ks, Key const & parentKey) const
     608             : {
     609           0 :         Key key = parentKey;
     610           0 :         std::vector<std::string> placements;
     611           0 :         placements.push_back ("getresolver");
     612           0 :         placements.push_back ("pregetstorage");
     613           0 :         placements.push_back ("getstorage");
     614           0 :         placements.push_back ("postgetstorage");
     615           0 :         for (auto const & placement : placements)
     616             :         {
     617           0 :                 auto currentPlugins = plugins.find (placement);
     618           0 :                 if (currentPlugins == plugins.end ()) continue;
     619           0 :                 for (auto const & plugin : currentPlugins->second)
     620             :                 {
     621           0 :                         plugin->get (ks, key);
     622             :                 }
     623             :         }
     624           0 : }
     625             : 
     626           0 : void ImportExportBackend::exportToFile (KeySet const & cks, Key const & parentKey) const
     627             : {
     628           0 :         KeySet ks = cks;
     629           0 :         Key key = parentKey;
     630           0 :         std::vector<std::string> placements;
     631           0 :         placements.push_back ("setresolver");
     632           0 :         placements.push_back ("presetstorage");
     633           0 :         placements.push_back ("setstorage");
     634           0 :         placements.push_back ("precommit");
     635           0 :         placements.push_back ("commit");
     636           0 :         placements.push_back ("postcommit");
     637           0 :         for (auto const & placement : placements)
     638             :         {
     639           0 :                 auto currentPlugins = plugins.find (placement);
     640           0 :                 if (currentPlugins == plugins.end ()) continue;
     641           0 :                 for (auto const & plugin : currentPlugins->second)
     642             :                 {
     643           0 :                         plugin->set (ks, key);
     644             :                 }
     645             :         }
     646           0 : }
     647             : } // namespace tools
     648             : } // namespace kdb

Generated by: LCOV version 1.13