std::vector<PluginSpec> PluginVariantDatabase::getPluginVariantsFromGenconf (PluginSpec const & whichplugin, KeySet const & genconf, KeySet const & sysconf) const { std::vector<PluginSpec> result; KeySet ksToIterate (genconf); for (auto kCurrent : ksToIterate) { Key kCurrentTest (kCurrent.getNamespace () + "/", KEY_END); kCurrentTest.addBaseName (kCurrent.getBaseName ()); // e.g. system/space if (kCurrentTest == kCurrent) { PluginSpec variant (whichplugin); KeySet ksVariantConfToAdd; // new base for plugin conf Key kVariantPluginConf ("system/", KEY_END); // take variant config from genconf and transform it to proper plugin conf, // e.g. system/space/config/format -> system/format Key kVariantConf (kCurrentTest); kVariantConf.addBaseName ("config"); // e.g. system/space/config this->addKeysBelowKeyToConf (kVariantConf, genconf, kVariantPluginConf, ksVariantConfToAdd); // TODO plugin infos // check if the variant was disabled : system/elektra/plugins/simpleini/variants/space/disable Key kDisable = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "disable")); if (kDisable && kDisable.getString () == "1") { continue; // skip this variant } // check if an override is available : system/elektra/plugins/simpleini/variants/space/override Key kOverride = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "override")); if (kOverride && kOverride.getString () == "1") { // first delete config from genconf entirely ksVariantConfToAdd.clear (); Key kVariantSysconf (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "config")); this->addKeysBelowKeyToConf (kVariantSysconf, sysconf, kVariantPluginConf, ksVariantConfToAdd); } if (ksVariantConfToAdd.size () == 0) { continue; // no config means no variant } variant.appendConfig (ksVariantConfToAdd); result.push_back (variant); } } std::vector<PluginSpec> resFromSysconf (this->getPluginVariantsFromSysconf (whichplugin, sysconf, genconf)); result.insert (result.end (), resFromSysconf.begin (), resFromSysconf.end ()); return result; }
std::vector<PluginSpec> PluginVariantDatabase::getPluginVariantsFromSysconf (PluginSpec const & whichplugin, KeySet const & sysconf, KeySet const & genconfToIgnore) const { std::vector<PluginSpec> result; KeySet ksSysconf (sysconf); // first find possible variants Key kVariantBase ("system/elektra/plugins", KEY_END); kVariantBase.addBaseName (whichplugin.getName ()); kVariantBase.addBaseName ("variants"); KeySet ksPluginVariantSysconf (ksSysconf.cut (kVariantBase)); KeySet ksToIterate (ksPluginVariantSysconf); for (auto kCurrent : ksToIterate) { Key kCurrentTest (kVariantBase); kCurrentTest.addBaseName (kCurrent.getBaseName ()); if (kCurrentTest == kCurrent) { PluginSpec variant (whichplugin); KeySet ksVariantConfToAdd; // new base for plugin conf Key kVariantPluginConf ("system/", KEY_END); // add system conf for plugin variant Key kVariantSysconf (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "config")); this->addKeysBelowKeyToConf (kVariantSysconf, ksPluginVariantSysconf, kVariantPluginConf, ksVariantConfToAdd); // check if the variant was disabled : system/elektra/plugins/simpleini/variants/space/disable Key kDisable = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "disable")); if (kDisable && kDisable.getString () == "1") { continue; // skip this variant } // check if the variant is in the genconfToIgnore list Key kGenconfVariant (kVariantPluginConf); kGenconfVariant.addBaseName (kCurrent.getBaseName ()); Key kIgnore = genconfToIgnore.lookup (kGenconfVariant); if (kIgnore) { continue; // this variant was added by genconf already } if (ksVariantConfToAdd.size () == 0) { continue; // no config means no variant } variant.appendConfig (ksVariantConfToAdd); result.push_back (variant); } } return result; }
/** * @brief Add a plugin. * * @pre Needs to be a unique new name (use refname if you want to add the same module multiple times) * * Will automatically resolve virtual plugins to actual plugins. * * Also calls the checkconf function if provided by the plugin. The checkconf function has the * following signature: int checkconf (Key * errorKey, KeySet * config) and allows a plugin to * verify its configuration at mount time. * * @see resolveNeeds() * @param plugin */ void BackendBuilder::addPlugin (PluginSpec const & plugin) { typedef int (*checkConfPtr) (ckdb::Key *, ckdb::KeySet *); for (auto & p : toAdd) { if (p.getFullName () == plugin.getFullName ()) { throw PluginAlreadyInserted (plugin.getFullName ()); } } PluginSpec newPlugin = plugin; // if the plugin is actually a provider use it (otherwise we will get our name back): PluginSpec provides = pluginDatabase->lookupProvides (plugin.getName ()); if (provides.getName () != newPlugin.getName ()) { // keep our config and refname newPlugin.setName (provides.getName ()); newPlugin.appendConfig (provides.getConfig ()); } // call plugin's checkconf function (if provided) // this enables a plugin to verify its configuration at mount time checkConfPtr checkConfFunction = reinterpret_cast<checkConfPtr> (pluginDatabase->getSymbol (newPlugin, "checkconf")); if (checkConfFunction) { ckdb::Key * errorKey = ckdb::keyNew (0); // merge plugin config and backend config together ckdb::KeySet * pluginConfig = newPlugin.getConfig ().dup (); ckdb::ksAppend (pluginConfig, backendConf.getKeySet ()); // call the plugin's checkconf function int checkResult = checkConfFunction (errorKey, pluginConfig); if (checkResult == -1) { ckdb::ksDel (pluginConfig); throw PluginConfigInvalid (errorKey); } else if (checkResult == 1) { // separate plugin config from the backend config ckdb::Key * backendParent = ckdb::keyNew ("system/", KEY_END); ckdb::KeySet * newBackendConfig = ckdb::ksCut (pluginConfig, backendParent); // take over the new configuration KeySet modifiedPluginConfig = KeySet (pluginConfig); KeySet modifiedBackendConfig = KeySet (newBackendConfig); newPlugin.setConfig (modifiedPluginConfig); setBackendConfig (modifiedBackendConfig); ckdb::keyDel (backendParent); } else { ckdb::ksDel (pluginConfig); } ckdb::keyDel (errorKey); } toAdd.push_back (newPlugin); sort (); }