/* * Copyright (c) 2011-2016, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "version.h" #include "ParameterMgr.h" #include "ConfigurationAccessContext.h" #include "XmlParameterSerializingContext.h" #include "XmlElementSerializingContext.h" #include "SystemClass.h" #include "ElementLibrarySet.h" #include "SubsystemLibrary.h" #include "NamedElementBuilderTemplate.h" #include "KindElementBuilderTemplate.h" #include "ElementBuilderTemplate.h" #include "SelectionCriterionType.h" #include "SubsystemElementBuilder.h" #include "FileIncluderElementBuilder.h" #include "SelectionCriteria.h" #include "ComponentType.h" #include "ComponentInstance.h" #include "ParameterBlockType.h" #include "BooleanParameterType.h" #include "IntegerParameterType.h" #include "FixedPointParameterType.h" #include "FloatingPointParameterType.h" #include "ParameterBlackboard.h" #include "Parameter.h" #include "ParameterAccessContext.h" #include "ParameterFrameworkConfiguration.h" #include "FrameworkConfigurationGroup.h" #include "PluginLocation.h" #include "SubsystemPlugins.h" #include "FrameworkConfigurationLocation.h" #include "ConfigurableDomains.h" #include "ConfigurableDomain.h" #include "DomainConfiguration.h" #include "XmlDomainSerializingContext.h" #include "XmlDomainExportContext.h" #include "XmlDomainImportContext.h" #include "BitParameterBlockType.h" #include "BitParameterType.h" #include "StringParameterType.h" #include "EnumParameterType.h" #include "BackgroundRemoteProcessorServer.h" #include "ElementLocator.h" #include "CompoundRule.h" #include "SelectionCriterionRule.h" #include "SimulatedBackSynchronizer.h" #include "HardwareBackSynchronizer.h" #include <cassert> #include "ParameterHandle.h" #include "LinearParameterAdaptation.h" #include "LogarithmicParameterAdaptation.h" #include "EnumValuePair.h" #include "Subsystem.h" #include "XmlStreamDocSink.h" #include "XmlMemoryDocSink.h" #include "XmlDocSource.h" #include "XmlMemoryDocSource.h" #include "SelectionCriteriaDefinition.h" #include "Utility.h" #include "Memory.hpp" #include <sstream> #include <fstream> #include <algorithm> #include <stdexcept> #include <mutex> #include <iomanip> #include "convert.hpp" #define base CElement /** Private macro helper to declare a new context * * Context declaration always need logger and logging prefix to be * passed as parameters. * This macro aims to avoid this boring notation. * This macro should be called only once in a scope. Nested scopes can * call this macro too, as variable shadowing is supported. */ #define LOG_CONTEXT(contextTitle) core::log::Context context(_logger, contextTitle) #ifdef SIMULATION // In simulation, back synchronization of the blackboard won't probably work // We need to ensure though the blackboard is initialized with valid data typedef CSimulatedBackSynchronizer BackSynchronizer; #else // Real back synchronizer from subsystems typedef CHardwareBackSynchronizer BackSynchronizer; #endif using std::string; using std::list; using std::vector; using std::ostringstream; using std::ofstream; using std::ifstream; using std::mutex; using std::lock_guard; // FIXME: integrate ParameterMgr to core namespace using namespace core; // Used for remote processor server creation typedef IRemoteProcessorServerInterface *(*CreateRemoteProcessorServer)( uint16_t uiPort, IRemoteCommandHandler *pCommandHandler); // Config File System looks normally like this: // --------------------------------------------- //|-- <ParameterFrameworkConfiguration>.xml //|-- schemas //| `-- *.xsd //|-- Settings //| `-- <SystemClassName folder>* //| |-- <ConfigurableDomains>.xml //| `-- <Settings>.bin? //`-- Structure // `-- <SystemClassName folder>* // |-- <SystemClassName>Class.xml // `-- <Subsystem>.xml* // -------------------------------------------- // Remote command parser array const CParameterMgr::SRemoteCommandParserItem CParameterMgr::gastRemoteCommandParserItems[] = { /// Version {"version", &CParameterMgr::versionCommandProcess, 0, "", "Show version"}, /// Status {"status", &CParameterMgr::statusCommandProcess, 0, "", "Show current status"}, /// Tuning Mode {"setTuningMode", &CParameterMgr::setTuningModeCommandProcess, 1, "on|off*", "Turn on or off Tuning Mode"}, {"getTuningMode", &CParameterMgr::getTuningModeCommandProcess, 0, "", "Show Tuning Mode"}, /// Value Space {"setValueSpace", &CParameterMgr::setValueSpaceCommandProcess, 1, "raw|real*", "Assigns Value Space used for parameter value interpretation"}, {"getValueSpace", &CParameterMgr::getValueSpaceCommandProcess, 0, "", "Show Value Space"}, /// Output Raw Format {"setOutputRawFormat", &CParameterMgr::setOutputRawFormatCommandProcess, 1, "dec*|hex", "Assigns format used to output parameter values when in raw Value Space"}, {"getOutputRawFormat", &CParameterMgr::getOutputRawFormatCommandProcess, 0, "", "Show Output Raw Format"}, /// Sync {"setAutoSync", &CParameterMgr::setAutoSyncCommandProcess, 1, "on*|off", "Turn on or off automatic synchronization to hardware while in Tuning Mode"}, {"getAutoSync", &CParameterMgr::getAutoSyncCommandProcess, 0, "", "Show Auto Sync state"}, {"sync", &CParameterMgr::syncCommandProcess, 0, "", "Synchronize current settings to hardware while in Tuning Mode and Auto Sync off"}, /// Criteria {"listCriteria", &CParameterMgr::listCriteriaCommandProcess, 0, "[CSV|XML]", "List selection criteria"}, /// Domains {"listDomains", &CParameterMgr::listDomainsCommandProcess, 0, "", "List configurable domains"}, {"dumpDomains", &CParameterMgr::dumpDomainsCommandProcess, 0, "", "Show all domains and configurations, including applicability conditions"}, {"createDomain", &CParameterMgr::createDomainCommandProcess, 1, "<domain>", "Create new configurable domain"}, {"deleteDomain", &CParameterMgr::deleteDomainCommandProcess, 1, "<domain>", "Delete configurable domain"}, {"deleteAllDomains", &CParameterMgr::deleteAllDomainsCommandProcess, 0, "", "Delete all configurable domains"}, {"renameDomain", &CParameterMgr::renameDomainCommandProcess, 2, "<domain> <new name>", "Rename configurable domain"}, {"setSequenceAwareness", &CParameterMgr::setSequenceAwarenessCommandProcess, 1, "<domain> true|false*", "Set configurable domain sequence awareness"}, {"getSequenceAwareness", &CParameterMgr::getSequenceAwarenessCommandProcess, 1, "<domain>", "Get configurable domain sequence awareness"}, {"listDomainElements", &CParameterMgr::listDomainElementsCommandProcess, 1, "<domain>", "List elements associated to configurable domain"}, {"addElement", &CParameterMgr::addElementCommandProcess, 2, "<domain> <elem path>", "Associate element at given path to configurable domain"}, {"removeElement", &CParameterMgr::removeElementCommandProcess, 2, "<domain> <elem path>", "Dissociate element at given path from configurable domain"}, {"splitDomain", &CParameterMgr::splitDomainCommandProcess, 2, "<domain> <elem path>", "Split configurable domain at given associated element path"}, /// Configurations {"listConfigurations", &CParameterMgr::listConfigurationsCommandProcess, 1, "<domain>", "List domain configurations"}, {"createConfiguration", &CParameterMgr::createConfigurationCommandProcess, 2, "<domain> <configuration>", "Create new domain configuration"}, {"deleteConfiguration", &CParameterMgr::deleteConfigurationCommandProcess, 2, "<domain> <configuration>", "Delete domain configuration"}, {"renameConfiguration", &CParameterMgr::renameConfigurationCommandProcess, 3, "<domain> <configuration> <new name>", "Rename domain configuration"}, {"saveConfiguration", &CParameterMgr::saveConfigurationCommandProcess, 2, "<domain> <configuration>", "Save current settings into configuration"}, {"restoreConfiguration", &CParameterMgr::restoreConfigurationCommandProcess, 2, "<domain> <configuration>", "Restore current settings from configuration"}, {"setElementSequence", &CParameterMgr::setElementSequenceCommandProcess, 3, "<domain> <configuration> <elem path list>", "Set element application order for configuration"}, {"getElementSequence", &CParameterMgr::getElementSequenceCommandProcess, 2, "<domain> <configuration>", "Get element application order for configuration"}, {"setRule", &CParameterMgr::setRuleCommandProcess, 3, "<domain> <configuration> <rule>", "Set configuration application rule"}, {"clearRule", &CParameterMgr::clearRuleCommandProcess, 2, "<domain> <configuration>", "Clear configuration application rule"}, {"getRule", &CParameterMgr::getRuleCommandProcess, 2, "<domain> <configuration>", "Get configuration application rule"}, /// Elements/Parameters {"listElements", &CParameterMgr::listElementsCommandProcess, 1, "<elem path>|/", "List elements under element at given path or root"}, {"listParameters", &CParameterMgr::listParametersCommandProcess, 1, "<elem path>|/", "List parameters under element at given path or root"}, {"getElementStructureXML", &CParameterMgr::getElementStructureXMLCommandProcess, 1, "<elem path>", "Get structure of element at given path in XML format"}, {"getElementBytes", &CParameterMgr::getElementBytesCommandProcess, 1, "<elem path>", "Get settings of element at given path in Byte Array format"}, {"setElementBytes", &CParameterMgr::setElementBytesCommandProcess, 2, "<elem path> <values>", "Set settings of element at given path in Byte Array format"}, {"getElementXML", &CParameterMgr::getElementXMLCommandProcess, 1, "<elem path>", "Get settings of element at given path in XML format"}, {"setElementXML", &CParameterMgr::setElementXMLCommandProcess, 2, "<elem path> <values>", "Set settings of element at given path in XML format"}, {"dumpElement", &CParameterMgr::dumpElementCommandProcess, 1, "<elem path>", "Dump structure and content of element at given path"}, {"getElementSize", &CParameterMgr::getElementSizeCommandProcess, 1, "<elem path>", "Show size of element at given path"}, {"showProperties", &CParameterMgr::showPropertiesCommandProcess, 1, "<elem path>", "Show properties of element at given path"}, {"getParameter", &CParameterMgr::getParameterCommandProcess, 1, "<param path>", "Get value for parameter at given path"}, {"setParameter", &CParameterMgr::setParameterCommandProcess, 2, "<param path> <value>", "Set value for parameter at given path"}, {"listBelongingDomains", &CParameterMgr::listBelongingDomainsCommandProcess, 1, "<elem path>", "List domain(s) element at given path belongs to"}, {"listAssociatedDomains", &CParameterMgr::listAssociatedDomainsCommandProcess, 1, "<elem path>", "List domain(s) element at given path is associated to"}, {"getConfigurationParameter", &CParameterMgr::getConfigurationParameterCommandProcess, 3, "<domain> <configuration> <param path>", "Get value for parameter at given path from configuration"}, {"setConfigurationParameter", &CParameterMgr::setConfigurationParameterCommandProcess, 4, "<domain> <configuration> <param path> <value>", "Set value for parameter at given path to configuration"}, {"showMapping", &CParameterMgr::showMappingCommandProcess, 1, "<elem path>", "Show mapping for an element at given path"}, /// Browse {"listAssociatedElements", &CParameterMgr::listAssociatedElementsCommandProcess, 0, "", "List element sub-trees associated to at least one configurable domain"}, {"listConflictingElements", &CParameterMgr::listConflictingElementsCommandProcess, 0, "", "List element sub-trees contained in more than one configurable domain"}, {"listRogueElements", &CParameterMgr::listRogueElementsCommandProcess, 0, "", "List element sub-trees owned by no configurable domain"}, /// Settings Import/Export {"exportDomainsXML", &CParameterMgr::exportDomainsXMLCommandProcess, 1, "<file path> ", "Export domains to an XML file (provide an absolute path or relative" "to the client's working directory)"}, {"importDomainsXML", &CParameterMgr::importDomainsXMLCommandProcess, 1, "<file path>", "Import domains from an XML file (provide an absolute path or relative" "to the client's working directory)"}, {"exportDomainsWithSettingsXML", &CParameterMgr::exportDomainsWithSettingsXMLCommandProcess, 1, "<file path> ", "Export domains including settings to XML file (provide an absolute path or relative" "to the client's working directory)"}, {"exportDomainWithSettingsXML", &CParameterMgr::exportDomainWithSettingsXMLCommandProcess, 2, "<domain> <file path> ", "Export a single given domain including settings to XML file" " (provide an absolute path or relative to the client's" " working directory)"}, {"importDomainsWithSettingsXML", &CParameterMgr::importDomainsWithSettingsXMLCommandProcess, 1, "<file path>", "Import domains including settings from XML file (provide an absolute path or relative" "to the client's working directory)"}, {"importDomainWithSettingsXML", &CParameterMgr::importDomainWithSettingsXMLCommandProcess, 1, "<file path> [overwrite]", "Import a single domain including settings from XML file." " Does not overwrite an existing domain unless 'overwrite' is passed as second" " argument. Provide an absolute path or relative to the client's working directory)"}, {"getDomainsWithSettingsXML", &CParameterMgr::getDomainsWithSettingsXMLCommandProcess, 0, "", "Print domains including settings as XML"}, {"getDomainWithSettingsXML", &CParameterMgr::getDomainWithSettingsXMLCommandProcess, 1, "<domain>", "Print the given domain including settings as XML"}, {"setDomainsWithSettingsXML", &CParameterMgr::setDomainsWithSettingsXMLCommandProcess, 1, "<xml configurable domains>", "Import domains including settings from XML string"}, {"setDomainWithSettingsXML", &CParameterMgr::setDomainWithSettingsXMLCommandProcess, 1, "<xml configurable domain> [overwrite]", "Import domains including settings from XML" " string. Does not overwrite an existing domain unless 'overwrite' is passed as second" " argument"}, /// Structure Export {"getSystemClassXML", &CParameterMgr::getSystemClassXMLCommandProcess, 0, "", "Print parameter structure as XML"}, /// Deprecated Commands {"getDomainsXML", &CParameterMgr::getDomainsWithSettingsXMLCommandProcess, 0, "", "DEPRECATED COMMAND, please use getDomainsWithSettingsXML"}, }; // Remote command parsers array Size CParameterMgr::CParameterMgr(const string &strConfigurationFilePath, log::ILogger &logger) : _pMainParameterBlackboard(new CParameterBlackboard), _pElementLibrarySet(new CElementLibrarySet), _xmlConfigurationUri(CXmlDocSource::mkUri(strConfigurationFilePath, "")), _logger(logger) { // Deal with children addChild(new CParameterFrameworkConfiguration); addChild(new CSelectionCriteria); addChild(new CSystemClass(_logger)); addChild(new CConfigurableDomains); } CParameterMgr::~CParameterMgr() { // Children delete _pRemoteProcessorServer; delete _pMainParameterBlackboard; delete _pElementLibrarySet; } string CParameterMgr::getKind() const { return "ParameterMgr"; } // Version string CParameterMgr::getVersion() const { return PARAMETER_FRAMEWORK_VERSION; } bool CParameterMgr::load(string &strError) { LOG_CONTEXT("Loading"); feedElementLibraries(); // Load Framework configuration if (!loadFrameworkConfiguration(strError)) { return false; } if (!loadSubsystems(strError)) { return false; } // Load structure if (!loadStructure(strError)) { return false; } // Load settings if (!loadSettings(strError)) { return false; } // Init flow of element tree if (!init(strError)) { return false; } { LOG_CONTEXT("Main blackboard back synchronization"); // Back synchronization for areas in parameter blackboard not covered by any domain BackSynchronizer(getConstSystemClass(), _pMainParameterBlackboard).sync(); } // We're done loading the settings and back synchronizing CConfigurableDomains *pConfigurableDomains = getConfigurableDomains(); // We need to ensure all domains are valid pConfigurableDomains->validate(_pMainParameterBlackboard); // Log selection criterion states { LOG_CONTEXT("Criterion states"); const CSelectionCriteria *selectionCriteria = getConstSelectionCriteria(); list<string> criteria; selectionCriteria->listSelectionCriteria(criteria, true, false); info() << criteria; } // Subsystem can not ask for resync as they have not been synced yet getSystemClass()->cleanSubsystemsNeedToResync(); // At initialization, check subsystems that need resync doApplyConfigurations(true); // Start remote processor server if appropriate return handleRemoteProcessingInterface(strError); } bool CParameterMgr::loadFrameworkConfiguration(string &strError) { LOG_CONTEXT("Loading framework configuration"); // Parse Structure XML file CXmlElementSerializingContext elementSerializingContext(strError); _xmlDoc *doc = CXmlDocSource::mkXmlDoc(_xmlConfigurationUri, true, true, elementSerializingContext); if (doc == NULL) { return false; } if (!xmlParse(elementSerializingContext, getFrameworkConfiguration(), doc, _xmlConfigurationUri, EFrameworkConfigurationLibrary)) { return false; } // Set class name to system class and configurable domains getSystemClass()->setName(getConstFrameworkConfiguration()->getSystemClassName()); getConfigurableDomains()->setName(getConstFrameworkConfiguration()->getSystemClassName()); // Get subsystem plugins elements _pSubsystemPlugins = static_cast<const CSubsystemPlugins *>( getConstFrameworkConfiguration()->findChild("SubsystemPlugins")); if (!_pSubsystemPlugins) { strError = "Parameter Framework Configuration: couldn't find SubsystemPlugins element"; return false; } // Log tuning availability info() << "Tuning " << (getConstFrameworkConfiguration()->isTuningAllowed() ? "allowed" : "prohibited"); return true; } bool CParameterMgr::loadSubsystems(std::string &error) { LOG_CONTEXT("Loading subsystem plugins"); // Load subsystems bool isSuccess = getSystemClass()->loadSubsystems(error, _pSubsystemPlugins, !_bFailOnMissingSubsystem); if (isSuccess) { info() << "All subsystem plugins successfully loaded"; if (!error.empty()) { // Log missing subsystems as info info() << error; } } else { warning() << error; } return isSuccess; } bool CParameterMgr::loadStructure(string &strError) { // Retrieve system to load structure to CSystemClass *pSystemClass = getSystemClass(); LOG_CONTEXT("Loading " + pSystemClass->getName() + " system class structure"); // Get structure description element const CFrameworkConfigurationLocation *pStructureDescriptionFileLocation = static_cast<const CFrameworkConfigurationLocation *>( getConstFrameworkConfiguration()->findChildOfKind("StructureDescriptionFileLocation")); if (!pStructureDescriptionFileLocation) { strError = "No StructureDescriptionFileLocation element found for SystemClass " + pSystemClass->getName(); return false; } // Parse Structure XML file CParameterAccessContext accessContext(strError); CXmlParameterSerializingContext parameterBuildContext(accessContext, strError); { // Get structure URI string structureUri = CXmlDocSource::mkUri(_xmlConfigurationUri, pStructureDescriptionFileLocation->getUri()); LOG_CONTEXT("Importing system structure from file " + structureUri); _xmlDoc *doc = CXmlDocSource::mkXmlDoc(structureUri, true, true, parameterBuildContext); if (doc == NULL) { return false; } if (!xmlParse(parameterBuildContext, pSystemClass, doc, structureUri, EParameterCreationLibrary)) { return false; } } // Initialize offsets pSystemClass->setOffset(0); // Initialize main blackboard's size _pMainParameterBlackboard->setSize(pSystemClass->getFootPrint()); return true; } bool CParameterMgr::loadSettings(string &strError) { string strLoadError; bool success = loadSettingsFromConfigFile(strLoadError); if (!success && !_bFailOnFailedSettingsLoad) { // Load can not fail, ie continue but log the load errors warning() << strLoadError; warning() << "Failed to load settings, continue without domains."; success = true; } if (!success) { // Propagate the litteral error only if the function fails strError = strLoadError; return false; } return true; } bool CParameterMgr::loadSettingsFromConfigFile(string &strError) { LOG_CONTEXT("Loading settings"); // Get settings configuration element const CFrameworkConfigurationGroup *pParameterConfigurationGroup = static_cast<const CFrameworkConfigurationGroup *>( getConstFrameworkConfiguration()->findChildOfKind("SettingsConfiguration")); if (!pParameterConfigurationGroup) { // No settings to load return true; } // Get configurable domains element const CFrameworkConfigurationLocation *pConfigurableDomainsFileLocation = static_cast<const CFrameworkConfigurationLocation *>( pParameterConfigurationGroup->findChildOfKind("ConfigurableDomainsFileLocation")); if (!pConfigurableDomainsFileLocation) { strError = "No ConfigurableDomainsFileLocation element found for SystemClass " + getSystemClass()->getName(); return false; } // Get destination root element CConfigurableDomains *pConfigurableDomains = getConfigurableDomains(); // Get Xml configuration domains URI string configurationDomainsUri = CXmlDocSource::mkUri(_xmlConfigurationUri, pConfigurableDomainsFileLocation->getUri()); // Parse configuration domains XML file CXmlDomainImportContext xmlDomainImportContext(strError, true, *getSystemClass()); // Selection criteria definition for rule creation xmlDomainImportContext.setSelectionCriteriaDefinition( getConstSelectionCriteria()->getSelectionCriteriaDefinition()); // Auto validation of configurations xmlDomainImportContext.setAutoValidationRequired(true); info() << "Importing configurable domains from file " << configurationDomainsUri << " with settings"; _xmlDoc *doc = CXmlDocSource::mkXmlDoc(configurationDomainsUri, true, true, xmlDomainImportContext); if (doc == NULL) { return false; } return xmlParse(xmlDomainImportContext, pConfigurableDomains, doc, _xmlConfigurationUri, EParameterConfigurationLibrary, true, "SystemClassName"); } // XML parsing bool CParameterMgr::xmlParse(CXmlElementSerializingContext &elementSerializingContext, CElement *pRootElement, _xmlDoc *doc, const string &baseUri, CParameterMgr::ElementLibrary eElementLibrary, bool replace, const string &strNameAttributeName) { // Init serializing context elementSerializingContext.set(_pElementLibrarySet->getElementLibrary(eElementLibrary), baseUri); CXmlDocSource docSource(doc, _bValidateSchemasOnStart, pRootElement->getXmlElementName(), pRootElement->getName(), strNameAttributeName); docSource.setSchemaBaseUri(getSchemaUri()); // Start clean auto clean = [replace, &pRootElement] { if (replace) { pRootElement->clean(); } }; clean(); CXmlMemoryDocSink memorySink(pRootElement); if (!memorySink.process(docSource, elementSerializingContext)) { clean(); return false; } return true; } // Init bool CParameterMgr::init(string &strError) { return base::init(strError); } // Selection criteria interface CSelectionCriterionType *CParameterMgr::createSelectionCriterionType(bool bIsInclusive) { // Propagate return getSelectionCriteria()->createSelectionCriterionType(bIsInclusive); } CSelectionCriterion *CParameterMgr::createSelectionCriterion( const string &strName, const CSelectionCriterionType *pSelectionCriterionType) { // Propagate return getSelectionCriteria()->createSelectionCriterion(strName, pSelectionCriterionType, _logger); } // Selection criterion retrieval CSelectionCriterion *CParameterMgr::getSelectionCriterion(const string &strName) { // Propagate return getSelectionCriteria()->getSelectionCriterion(strName); } // Configuration application void CParameterMgr::applyConfigurations() { LOG_CONTEXT("Configuration application request"); // Lock state lock_guard<mutex> autoLock(getBlackboardMutex()); if (!_bTuningModeIsOn) { // Apply configuration(s) doApplyConfigurations(false); } else { warning() << "Configurations were not applied because the TuningMode is on"; } } const CConfigurableElement *CParameterMgr::getConfigurableElement(const string &strPath, string &strError) const { CPathNavigator pathNavigator(strPath); // Nagivate through system class if (!pathNavigator.navigateThrough(getConstSystemClass()->getName(), strError)) { return NULL; } // Find element const CElement *pElement = getConstSystemClass()->findDescendant(pathNavigator); if (!pElement) { strError = "Path not found: " + strPath; return NULL; } // Check found element is a parameter const CConfigurableElement *pConfigurableElement = static_cast<const CConfigurableElement *>(pElement); return pConfigurableElement; } CConfigurableElement *CParameterMgr::getConfigurableElement(const string &strPath, string &strError) { // Implement the mutable version by calling the const one and removing // the const from the result. const auto *constThis = this; return const_cast<CConfigurableElement *>(constThis->getConfigurableElement(strPath, strError)); } // Dynamic parameter handling CParameterHandle *CParameterMgr::createParameterHandle(const string &strPath, string &strError) { CConfigurableElement *pConfigurableElement = getConfigurableElement(strPath, strError); if (!pConfigurableElement) { // Element not found strError = "Element not found: " + strPath; return NULL; } if (!pConfigurableElement->isParameter()) { // Element is not parameter strError = "Not a parameter: " + strPath; return NULL; } // Convert as parameter and return new handle return new CParameterHandle(static_cast<CBaseParameter &>(*pConfigurableElement), *this); } // Dynamic element handling ElementHandle *CParameterMgr::createElementHandle(const std::string &path, std::string &error) { CConfigurableElement *pConfigurableElement; if (path == "/") { // Attempt to access root configurable element pConfigurableElement = getSystemClass(); } else { pConfigurableElement = getConfigurableElement(path, error); } if (!pConfigurableElement) { // Element not found error = "Element not found: " + path; return nullptr; } // The only reason why a heap object is returned instead of retuning by copy // is to inform the client of a failure through a nullptr. // It could be avoided (return by copy) with an // - optional equivalent (see boost::optional or std::experimental::optional) // - exception (but the api is noexcept) return new ElementHandle(*pConfigurableElement, *this); } void CParameterMgr::getSettingsAsBytes(const CConfigurableElement &element, std::vector<uint8_t> &settings) const { // Not useful as the get can not fail, // but the current design forces all serialization and deserialization to // have an error out string std::string error; // Prepare parameter access context for main blackboard. // No need to handle output raw format and value space as Byte arrays are hexa formatted CParameterAccessContext parameterAccessContext(error); parameterAccessContext.setParameterBlackboard(_pMainParameterBlackboard); // Get the settings element.getSettingsAsBytes(settings, parameterAccessContext); } bool CParameterMgr::setSettingsAsBytes(const CConfigurableElement &element, const std::vector<uint8_t> &settings, std::string &error) { // Prepare parameter access context for main blackboard. // Notes: // - No need to handle output raw format and value space as Byte arrays are interpreted as // raw formatted // - No check is done as to the intgrity of the input data. // This may lead to undetected out of range value assignment. // Use this functionality with caution CParameterAccessContext parameterAccessContext(error); parameterAccessContext.setParameterBlackboard(_pMainParameterBlackboard); parameterAccessContext.setAutoSync(autoSyncOn()); // Set the settings return element.setSettingsAsBytes(settings, parameterAccessContext); } void CParameterMgr::setFailureOnMissingSubsystem(bool bFail) { _bFailOnMissingSubsystem = bFail; } bool CParameterMgr::getFailureOnMissingSubsystem() const { return _bFailOnMissingSubsystem; } void CParameterMgr::setFailureOnFailedSettingsLoad(bool bFail) { _bFailOnFailedSettingsLoad = bFail; } bool CParameterMgr::getFailureOnFailedSettingsLoad() const { return _bFailOnFailedSettingsLoad; } const string &CParameterMgr::getSchemaUri() const { return _schemaUri; } void CParameterMgr::setSchemaUri(const string &schemaUri) { _schemaUri = schemaUri; } void CParameterMgr::setValidateSchemasOnStart(bool bValidate) { _bValidateSchemasOnStart = bValidate; } bool CParameterMgr::getValidateSchemasOnStart() const { return _bValidateSchemasOnStart; } /////////////////// Remote command parsers /// Version CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::versionCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { // Show version strResult = getVersion(); return CCommandHandler::ESucceeded; } /// Status CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::statusCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { // System class const CSystemClass *pSystemClass = getSystemClass(); // Show status /// General section utility::appendTitle(strResult, "General:"); // System class strResult += "System Class: "; strResult += pSystemClass->getName(); strResult += "\n"; // Tuning mode strResult += "Tuning Mode: "; strResult += tuningModeOn() ? "on" : "off"; strResult += "\n"; // Value space strResult += "Value Space: "; strResult += valueSpaceIsRaw() ? "raw" : "real"; strResult += "\n"; // Output raw format strResult += "Output Raw Format: "; strResult += outputRawFormatIsHex() ? "hex" : "dec"; strResult += "\n"; // Auto Sync strResult += "Auto Sync: "; strResult += autoSyncOn() ? "on" : "off"; strResult += "\n"; /// Subsystem list utility::appendTitle(strResult, "Subsystems:"); string strSubsystemList; pSystemClass->listChildrenPaths(strSubsystemList); strResult += strSubsystemList; /// Last applied configurations utility::appendTitle(strResult, "Last Applied [Pending] Configurations:"); string strLastAppliedConfigurations; getConfigurableDomains()->listLastAppliedConfigurations(strLastAppliedConfigurations); strResult += strLastAppliedConfigurations; /// Criteria states utility::appendTitle(strResult, "Selection Criteria:"); list<string> lstrSelectionCriteria; getSelectionCriteria()->listSelectionCriteria(lstrSelectionCriteria, false, true); // Concatenate the criterion list as the command result strResult += utility::asString(lstrSelectionCriteria); return CCommandHandler::ESucceeded; } /// Tuning Mode CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setTuningModeCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { if (remoteCommand.getArgument(0) == "on") { if (setTuningMode(true, strResult)) { return CCommandHandler::EDone; } } else if (remoteCommand.getArgument(0) == "off") { if (setTuningMode(false, strResult)) { return CCommandHandler::EDone; } } else { // Show usage return CCommandHandler::EShowUsage; } return CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getTuningModeCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { strResult = tuningModeOn() ? "on" : "off"; return CCommandHandler::ESucceeded; } /// Value Space CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setValueSpaceCommandProcess( const IRemoteCommand &remoteCommand, string & /*strResult*/) { if (remoteCommand.getArgument(0) == "raw") { setValueSpace(true); return CCommandHandler::EDone; } else if (remoteCommand.getArgument(0) == "real") { setValueSpace(false); return CCommandHandler::EDone; } else { // Show usage return CCommandHandler::EShowUsage; } return CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getValueSpaceCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { strResult = valueSpaceIsRaw() ? "raw" : "real"; return CCommandHandler::ESucceeded; } /// Output Raw Format CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setOutputRawFormatCommandProcess( const IRemoteCommand &remoteCommand, string & /*strResult*/) { if (remoteCommand.getArgument(0) == "hex") { setOutputRawFormat(true); return CCommandHandler::EDone; } else if (remoteCommand.getArgument(0) == "dec") { setOutputRawFormat(false); return CCommandHandler::EDone; } else { // Show usage return CCommandHandler::EShowUsage; } return CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getOutputRawFormatCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { strResult = outputRawFormatIsHex() ? "hex" : "dec"; return CCommandHandler::ESucceeded; } /// Sync CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setAutoSyncCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { if (remoteCommand.getArgument(0) == "on") { if (setAutoSync(true, strResult)) { return CCommandHandler::EDone; } } else if (remoteCommand.getArgument(0) == "off") { if (setAutoSync(false, strResult)) { return CCommandHandler::EDone; } } else { // Show usage return CCommandHandler::EShowUsage; } return CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getAutoSyncCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { strResult = autoSyncOn() ? "on" : "off"; return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::syncCommandProcess( const IRemoteCommand &, string &strResult) { return sync(strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } /// Criteria CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listCriteriaCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { if (remoteCommand.getArgumentCount() > 1) { return CCommandHandler::EShowUsage; } string strOutputFormat; // Look for optional arguments if (remoteCommand.getArgumentCount() == 1) { // Get requested format strOutputFormat = remoteCommand.getArgument(0); // Capitalize std::transform(strOutputFormat.begin(), strOutputFormat.end(), strOutputFormat.begin(), ::toupper); if (strOutputFormat != "XML" && strOutputFormat != "CSV") { return CCommandHandler::EShowUsage; } } if (strOutputFormat == "XML") { // Get Root element where to export from const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition = getConstSelectionCriteria()->getSelectionCriteriaDefinition(); if (!exportElementToXMLString(pSelectionCriteriaDefinition, "SelectionCriteria", CXmlSerializingContext{strResult}, strResult)) { return CCommandHandler::EFailed; } // Succeeded return CCommandHandler::ESucceeded; } else { // Requested format will be either CSV or human readable based on strOutputFormat content bool bHumanReadable = strOutputFormat.empty(); list<string> lstrResult; getSelectionCriteria()->listSelectionCriteria(lstrResult, true, bHumanReadable); // Concatenate the criterion list as the command result strResult += utility::asString(lstrResult); return CCommandHandler::ESucceeded; } } /// Domains CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listDomainsCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { getConfigurableDomains()->listDomains(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::createDomainCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return createDomain(remoteCommand.getArgument(0), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::deleteDomainCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return deleteDomain(remoteCommand.getArgument(0), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::deleteAllDomainsCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { return deleteAllDomains(strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::renameDomainCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return renameDomain(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setSequenceAwarenessCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Set property bool bSequenceAware; if (remoteCommand.getArgument(1) == "true") { bSequenceAware = true; } else if (remoteCommand.getArgument(1) == "false") { bSequenceAware = false; } else { // Show usage return CCommandHandler::EShowUsage; } return setSequenceAwareness(remoteCommand.getArgument(0), bSequenceAware, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getSequenceAwarenessCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Get property bool bSequenceAware; if (!getSequenceAwareness(remoteCommand.getArgument(0), bSequenceAware, strResult)) { return CCommandHandler::EFailed; } strResult = bSequenceAware ? "true" : "false"; return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listDomainElementsCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return getConfigurableDomains()->listDomainElements(remoteCommand.getArgument(0), strResult) ? CCommandHandler::ESucceeded : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::addElementCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return addConfigurableElementToDomain(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::removeElementCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return removeConfigurableElementFromDomain(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::splitDomainCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return split(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } /// Configurations CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listConfigurationsCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return getConstConfigurableDomains()->listConfigurations(remoteCommand.getArgument(0), strResult) ? CCommandHandler::ESucceeded : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::dumpDomainsCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { // Dummy error context string strError; utility::ErrorContext errorContext(strError); // Dump strResult = getConstConfigurableDomains()->dumpContent(errorContext); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::createConfigurationCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return createConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::deleteConfigurationCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return deleteConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::renameConfigurationCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return renameConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), remoteCommand.getArgument(2), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::saveConfigurationCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return saveConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::restoreConfigurationCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { core::Results result; if (!restoreConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), result)) { // Concatenate the error list as the command result strResult = utility::asString(result); return CCommandHandler::EFailed; } return CCommandHandler::EDone; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setElementSequenceCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Build configurable element path list std::vector<string> astrNewElementSequence; for (size_t argument = 2; argument < remoteCommand.getArgumentCount(); argument++) { astrNewElementSequence.push_back(remoteCommand.getArgument(argument)); } // Delegate to configurable domains return setElementSequence(remoteCommand.getArgument(0), remoteCommand.getArgument(1), astrNewElementSequence, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementSequenceCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Delegate to configurable domains return getConfigurableDomains()->getElementSequence(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::ESucceeded : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setRuleCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Delegate to configurable domains return setApplicationRule(remoteCommand.getArgument(0), remoteCommand.getArgument(1), remoteCommand.packArguments(2, remoteCommand.getArgumentCount() - 2), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::clearRuleCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Delegate to configurable domains return clearApplicationRule(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getRuleCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Delegate to configurable domains return getApplicationRule(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult) ? CCommandHandler::ESucceeded : CCommandHandler::EFailed; } /// Elements/Parameters CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listElementsCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass(), false); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } if (!pLocatedElement) { // List from root folder // Return system class qualified name pLocatedElement = getSystemClass(); } // Return sub-elements strResult += pLocatedElement->listQualifiedPaths(false); return CCommandHandler::ESucceeded; } /// Elements/Parameters CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listParametersCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass(), false); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } if (!pLocatedElement) { // List from root folder // Return system class qualified name pLocatedElement = getSystemClass(); } // Return sub-elements strResult += pLocatedElement->listQualifiedPaths(true); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementStructureXMLCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } // Use default access context for structure export CParameterAccessContext accessContext(strResult); if (!exportElementToXMLString(pLocatedElement, pLocatedElement->getXmlElementName(), CXmlParameterSerializingContext{accessContext, strResult}, strResult)) { return CCommandHandler::EFailed; } return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementBytesCommandProcess( const IRemoteCommand &remoteCommand, std::string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } const CConfigurableElement *pConfigurableElement = static_cast<CConfigurableElement *>(pLocatedElement); // Get the settings vector<uint8_t> bytes; getSettingsAsBytes(*pConfigurableElement, bytes); // Hexa formatting std::ostringstream ostream; ostream << std::hex << std::setfill('0'); // Format bytes for (auto byte : bytes) { // Convert to an int in order to avoid the "char" overload that would // print characters instead of numbers. ostream << "0x" << std::setw(2) << int{byte} << " "; } strResult = ostream.str(); if (not strResult.empty()) { // Remove the trailing space strResult.pop_back(); } return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setElementBytesCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Check tuning mode if (!checkTuningModeOn(strResult)) { return CCommandHandler::EFailed; } // Retrieve configurable element CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } const CConfigurableElement *pConfigurableElement = static_cast<CConfigurableElement *>(pLocatedElement); // Convert input data to binary vector<uint8_t> bytes; auto first = remoteCommand.getArguments().cbegin() + 1; auto last = remoteCommand.getArguments().cend(); try { std::transform(first, last, begin(bytes), [](decltype(*first) input) { uint8_t byte; if (!convertTo(input, byte)) { throw std::domain_error("Some values out of byte range"); } return byte; }); } catch (const std::domain_error &e) { strResult = e.what(); return CCommandHandler::EFailed; } // Set the settings if (!setSettingsAsBytes(*pConfigurableElement, bytes, strResult)) { return CCommandHandler::EFailed; } return CCommandHandler::EDone; } bool CParameterMgr::getSettingsAsXML(const CConfigurableElement *configurableElement, string &result) const { string error; CConfigurationAccessContext configContext(error, _pMainParameterBlackboard, _bValueSpaceIsRaw, _bOutputRawFormatIsHex, true); CXmlParameterSerializingContext xmlParameterContext(configContext, error); // Use a doc source by loading data from instantiated Configurable Domains CXmlMemoryDocSource memorySource(configurableElement, false, configurableElement->getXmlElementName()); // Use a doc sink that write the doc data in a string ostringstream output; CXmlStreamDocSink streamSink(output); if (not streamSink.process(memorySource, xmlParameterContext)) { result = error; return false; } result = output.str(); return true; } bool CParameterMgr::setSettingsAsXML(CConfigurableElement *configurableElement, const string &settings, string &error) { CConfigurationAccessContext configContext(error, _pMainParameterBlackboard, _bValueSpaceIsRaw, _bOutputRawFormatIsHex, false); CXmlParameterSerializingContext xmlParameterContext(configContext, error); // It doesn't make sense to resolve XIncludes on an imported file because // we can't reliably decide of a "base url" _xmlDoc *doc = CXmlDocSource::mkXmlDoc(settings, false, false, xmlParameterContext); if (doc == nullptr) { return false; } if (not xmlParse(xmlParameterContext, configurableElement, doc, "", EParameterConfigurationLibrary, false)) { return false; } if (_bAutoSyncOn) { CSyncerSet syncerSet; static_cast<CConfigurableElement *>(configurableElement)->fillSyncerSet(syncerSet); core::Results errors; if (not syncerSet.sync(*_pMainParameterBlackboard, false, &errors)) { error = utility::asString(errors); return false; } } return true; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementXMLCommandProcess( const IRemoteCommand &remoteCommand, string &result) { CElementLocator elementLocator(getSystemClass()); CElement *locatedElement = nullptr; if (not elementLocator.locate(remoteCommand.getArgument(0), &locatedElement, result)) { return CCommandHandler::EFailed; } if (not getSettingsAsXML(static_cast<CConfigurableElement *>(locatedElement), result)) { return CCommandHandler::EFailed; } return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setElementXMLCommandProcess( const IRemoteCommand &remoteCommand, string &result) { if (!checkTuningModeOn(result)) { return CCommandHandler::EFailed; } CElementLocator elementLocator(getSystemClass()); CElement *locatedElement = nullptr; if (not elementLocator.locate(remoteCommand.getArgument(0), &locatedElement, result)) { return CCommandHandler::EFailed; } if (not setSettingsAsXML(static_cast<CConfigurableElement *>(locatedElement), remoteCommand.getArgument(1), result)) { return CCommandHandler::EFailed; } return CCommandHandler::EDone; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::dumpElementCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } string strError; CParameterAccessContext parameterAccessContext(strError, _pMainParameterBlackboard, _bValueSpaceIsRaw, _bOutputRawFormatIsHex); // Dump elements strResult = pLocatedElement->dumpContent(parameterAccessContext); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementSizeCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } // Converted to actual sizable element const CConfigurableElement *pConfigurableElement = static_cast<const CConfigurableElement *>(pLocatedElement); // Get size as string strResult = pConfigurableElement->getFootprintAsString(); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::showPropertiesCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } // Convert element const CConfigurableElement *pConfigurableElement = static_cast<const CConfigurableElement *>(pLocatedElement); // Return element properties pConfigurableElement->showProperties(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getParameterCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { string strValue; if (!accessParameterValue(remoteCommand.getArgument(0), strValue, false, strResult)) { return CCommandHandler::EFailed; } // Succeeded strResult = strValue; return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setParameterCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { // Get value to set string strValue = remoteCommand.packArguments(1, remoteCommand.getArgumentCount() - 1); return accessParameterValue(remoteCommand.getArgument(0), strValue, true, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listBelongingDomainsCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } // Convert element const CConfigurableElement *pConfigurableElement = static_cast<const CConfigurableElement *>(pLocatedElement); // Return element belonging domains pConfigurableElement->listBelongingDomains(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listAssociatedDomainsCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) { return CCommandHandler::EFailed; } // Convert element const CConfigurableElement *pConfigurableElement = static_cast<const CConfigurableElement *>(pLocatedElement); // Return element belonging domains pConfigurableElement->listAssociatedDomains(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listAssociatedElementsCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { getConfigurableDomains()->listAssociatedElements(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listConflictingElementsCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { getConfigurableDomains()->listConflictingElements(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listRogueElementsCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { getSystemClass()->listRogueElements(strResult); return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: getConfigurationParameterCommandProcess(const IRemoteCommand &remoteCommand, string &strResult) { string strOutputValue; string strError; if (!accessConfigurationValue(remoteCommand.getArgument(0), remoteCommand.getArgument(1), remoteCommand.getArgument(2), strOutputValue, false, strError)) { strResult = strError; return CCommandHandler::EFailed; } // Succeeded strResult = strOutputValue; return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: setConfigurationParameterCommandProcess(const IRemoteCommand &remoteCommand, string &strResult) { // Get value to set string strValue = remoteCommand.packArguments(3, remoteCommand.getArgumentCount() - 3); bool bSuccess = accessConfigurationValue(remoteCommand.getArgument(0), remoteCommand.getArgument(1), remoteCommand.getArgument(2), strValue, true, strResult); return bSuccess ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::showMappingCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { if (!getParameterMapping(remoteCommand.getArgument(0), strResult)) { return CCommandHandler::EFailed; } return CCommandHandler::ESucceeded; } /// Settings Import/Export CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::exportDomainsXMLCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { string strFileName = remoteCommand.getArgument(0); return exportDomainsXml(strFileName, false, true, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::importDomainsXMLCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { return importDomainsXml(remoteCommand.getArgument(0), false, true, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: exportDomainsWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &strResult) { string strFileName = remoteCommand.getArgument(0); return exportDomainsXml(strFileName, true, true, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: exportDomainWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &result) { string domainName = remoteCommand.getArgument(0); string fileName = remoteCommand.getArgument(1); return exportSingleDomainXml(fileName, domainName, true, true, result) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: importDomainsWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &strResult) { return importDomainsXml(remoteCommand.getArgument(0), true, true, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: importDomainWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &strResult) { bool bOverwrite = false; // Look for optional arguments if (remoteCommand.getArgumentCount() > 1) { if (remoteCommand.getArgument(1) == "overwrite") { bOverwrite = true; } else { // Show usage return CCommandHandler::EShowUsage; } } return importSingleDomainXml(remoteCommand.getArgument(0), bOverwrite, true, true, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: getDomainsWithSettingsXMLCommandProcess(const IRemoteCommand & /*command*/, string &strResult) { if (!exportDomainsXml(strResult, true, false, strResult)) { return CCommandHandler::EFailed; } // Succeeded return CCommandHandler::ESucceeded; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getDomainWithSettingsXMLCommandProcess( const IRemoteCommand &remoteCommand, string &strResult) { string strDomainName = remoteCommand.getArgument(0); return exportSingleDomainXml(strResult, strDomainName, true, false, strResult) ? CCommandHandler::ESucceeded : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr:: setDomainsWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &strResult) { return importDomainsXml(remoteCommand.getArgument(0), true, false, strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setDomainWithSettingsXMLCommandProcess( const IRemoteCommand &remoteCommand, string &result) { bool overwrite = false; if (remoteCommand.getArgumentCount() > 1) { if (remoteCommand.getArgument(1) == "overwrite") { overwrite = true; } else { // Show usage return CCommandHandler::EShowUsage; } } return importSingleDomainXml(remoteCommand.getArgument(0), overwrite, true, false, result) ? CCommandHandler::EDone : CCommandHandler::EFailed; } CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getSystemClassXMLCommandProcess( const IRemoteCommand & /*command*/, string &strResult) { // Get Root element where to export from const CSystemClass *pSystemClass = getSystemClass(); // Use default access context for structure export CParameterAccessContext accessContext(strResult); if (!exportElementToXMLString(pSystemClass, pSystemClass->getXmlElementName(), CXmlParameterSerializingContext{accessContext, strResult}, strResult)) { return CCommandHandler::EFailed; } // Succeeded return CCommandHandler::ESucceeded; } // User set/get parameters in main BlackBoard bool CParameterMgr::accessParameterValue(const string &strPath, string &strValue, bool bSet, string &strError) { // Forbid write access when not in TuningMode if (bSet && !checkTuningModeOn(strError)) { return false; } // Define context CParameterAccessContext parameterAccessContext(strError, _pMainParameterBlackboard, _bValueSpaceIsRaw, _bOutputRawFormatIsHex); // Activate the auto synchronization with the hardware if (bSet) { parameterAccessContext.setAutoSync(_bAutoSyncOn); } return accessValue(parameterAccessContext, strPath, strValue, bSet, strError); } // User get parameter mapping bool CParameterMgr::getParameterMapping(const string &strPath, string &strResult) const { // Get the ConfigurableElement corresponding to strPath const CConfigurableElement *pConfigurableElement = getConfigurableElement(strPath, strResult); if (!pConfigurableElement) { return false; } // Find the list of the ancestors of the current ConfigurableElement that have a mapping auto configurableElementPath = pConfigurableElement->getConfigurableElementContext(); // Get the Subsystem containing the ConfigurableElement const CSubsystem *pSubsystem = pConfigurableElement->getBelongingSubsystem(); if (!pSubsystem) { strResult = "Unable to find the Subsystem containing the parameter"; return false; } // Fetch the mapping corresponding to the ConfigurableElement strResult = pSubsystem->getMapping(configurableElementPath); return true; } // User set/get parameters in specific Configuration BlackBoard bool CParameterMgr::accessConfigurationValue(const string &strDomain, const string &strConfiguration, const string &strPath, string &strValue, bool bSet, string &strError) { CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(strPath, &pLocatedElement, strError)) { return false; } // Convert element const CConfigurableElement *pConfigurableElement = static_cast<const CConfigurableElement *>(pLocatedElement); // Get the Configuration blackboard and the Base Offset of the configurable element in this // blackboard size_t baseOffset; bool bIsLastApplied; CParameterBlackboard *pConfigurationBlackboard = NULL; { pConfigurationBlackboard = getConstConfigurableDomains()->findConfigurationBlackboard( strDomain, strConfiguration, pConfigurableElement, baseOffset, bIsLastApplied, strError); if (!pConfigurationBlackboard) { warning() << "Fail: " << strError; return false; } } info() << "Element " << strPath << " in Domain " << strDomain << ", offset: " << pConfigurableElement->getOffset() << ", base offset: " << baseOffset; /// Update the Configuration Blackboard // Define Configuration context using Base Offset and keep Auto Sync off to prevent access to HW CParameterAccessContext parameterAccessContext( strError, pConfigurationBlackboard, _bValueSpaceIsRaw, _bOutputRawFormatIsHex, baseOffset); // Deactivate the auto synchronization with the hardware during the Configuration Blackboard // access (only Main Blackboard shall be synchronized, Configurations Blackboards are copied // into the Main Blackboard each time a configuration is restored but they are not synchronized // directly). if (bSet) { parameterAccessContext.setAutoSync(false); } // Access Value in the Configuration Blackboard if (!accessValue(parameterAccessContext, strPath, strValue, bSet, strError)) { return false; } /// If the Configuration is the last one applied, update the Main Blackboard as well if (bIsLastApplied) { // Define Main context parameterAccessContext.setParameterBlackboard(_pMainParameterBlackboard); // Activate the auto synchronization with the hardware if (bSet) { parameterAccessContext.setAutoSync(_bAutoSyncOn); } // Access Value in the Main Blackboard return accessValue(parameterAccessContext, strPath, strValue, bSet, strError); } return true; } // User set/get parameters bool CParameterMgr::accessValue(CParameterAccessContext ¶meterAccessContext, const string &strPath, string &strValue, bool bSet, string &strError) { // Lock state lock_guard<mutex> autoLock(getBlackboardMutex()); CPathNavigator pathNavigator(strPath); // Nagivate through system class if (!pathNavigator.navigateThrough(getConstSystemClass()->getName(), strError)) { parameterAccessContext.setError(strError); return false; } // Do the get return getConstSystemClass()->accessValue(pathNavigator, strValue, bSet, parameterAccessContext); } // Tuning mode bool CParameterMgr::setTuningMode(bool bOn, string &strError) { if (bOn == tuningModeOn()) { strError = "Tuning mode is already in the state requested"; return false; } // Tuning allowed? if (bOn && !getConstFrameworkConfiguration()->isTuningAllowed()) { strError = "Tuning prohibited"; return false; } // Lock state lock_guard<mutex> autoLock(getBlackboardMutex()); // Warn domains about exiting tuning mode if (!bOn) { // Ensure application of currently selected configurations // Force-apply configurations doApplyConfigurations(true); } // Store _bTuningModeIsOn = bOn; return true; } bool CParameterMgr::tuningModeOn() const { return _bTuningModeIsOn; } // Current value space for user set/get value interpretation void CParameterMgr::setValueSpace(bool bIsRaw) { _bValueSpaceIsRaw = bIsRaw; } bool CParameterMgr::valueSpaceIsRaw() { return _bValueSpaceIsRaw; } // Current Output Raw Format for user get value interpretation void CParameterMgr::setOutputRawFormat(bool bIsHex) { _bOutputRawFormatIsHex = bIsHex; } bool CParameterMgr::outputRawFormatIsHex() { return _bOutputRawFormatIsHex; } /// Sync // Automatic hardware synchronization control (during tuning session) bool CParameterMgr::setAutoSync(bool bAutoSyncOn, string &strError) { // Warn domains about turning auto sync back on if (bAutoSyncOn && !_bAutoSyncOn) { // Do the synchronization at system class level (could be optimized by keeping track of all // modified parameters) if (!sync(strError)) { return false; } } // Set Auto sync _bAutoSyncOn = bAutoSyncOn; return true; } bool CParameterMgr::autoSyncOn() const { return _bAutoSyncOn; } // Manual hardware synchronization control (during tuning session) bool CParameterMgr::sync(string &strError) { // Warn domains about turning auto sync back on if (_bAutoSyncOn) { strError = "Feature unavailable when Auto Sync is on"; return false; } // Get syncer set CSyncerSet syncerSet; // ... from system class getConstSystemClass()->fillSyncerSet(syncerSet); // Sync core::Results error; if (!syncerSet.sync(*_pMainParameterBlackboard, false, &error)) { strError = utility::asString(error); return false; }; return true; } // Configuration/Domains handling bool CParameterMgr::createDomain(const string &strName, string &strError) { LOG_CONTEXT("Creating configurable domain " + strName); // Check tuning mode if (!checkTuningModeOn(strError)) { return false; } // Delegate to configurable domains return logResult(getConfigurableDomains()->createDomain(strName, strError), strError); } bool CParameterMgr::deleteDomain(const string &strName, string &strError) { LOG_CONTEXT("Deleting configurable domain '" + strName + "'"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail: " << strError; return false; } // Delegate to configurable domains return logResult(getConfigurableDomains()->deleteDomain(strName, strError), strError); } bool CParameterMgr::renameDomain(const string &strName, const string &strNewName, string &strError) { LOG_CONTEXT("Renaming configurable domain '" + strName + "' to '" + strNewName + "'"); // Delegate to configurable domains return logResult(getConfigurableDomains()->renameDomain(strName, strNewName, strError), strError); } bool CParameterMgr::deleteAllDomains(string &strError) { LOG_CONTEXT("Deleting all configurable domains"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail: " << strError; return false; } // Delegate to configurable domains getConfigurableDomains()->deleteAllDomains(); info() << "Success"; return true; } bool CParameterMgr::setSequenceAwareness(const string &strName, bool bSequenceAware, string &strResult) { LOG_CONTEXT("Making domain '" + strName + "' sequence " + (bSequenceAware ? "aware" : "unaware")); // Check tuning mode if (!checkTuningModeOn(strResult)) { warning() << "Fail: " << strResult; return false; } return logResult( getConfigurableDomains()->setSequenceAwareness(strName, bSequenceAware, strResult), strResult); } bool CParameterMgr::getSequenceAwareness(const string &strName, bool &bSequenceAware, string &strResult) { return getConfigurableDomains()->getSequenceAwareness(strName, bSequenceAware, strResult); } bool CParameterMgr::createConfiguration(const string &strDomain, const string &strConfiguration, string &strError) { LOG_CONTEXT("Creating domain configuration '" + strConfiguration + "' into domain '" + strDomain + "'"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail: " << strError; return false; } // Delegate to configurable domains return logResult(getConfigurableDomains()->createConfiguration( strDomain, strConfiguration, _pMainParameterBlackboard, strError), strError); } bool CParameterMgr::renameConfiguration(const string &strDomain, const string &strConfiguration, const string &strNewConfiguration, string &strError) { LOG_CONTEXT("Renaming domain '" + strDomain + "''s configuration '" + strConfiguration + "' to '" + strNewConfiguration + "'"); return logResult(getConfigurableDomains()->renameConfiguration(strDomain, strConfiguration, strNewConfiguration, strError), strError); } bool CParameterMgr::deleteConfiguration(const string &strDomain, const string &strConfiguration, string &strError) { LOG_CONTEXT("Deleting configuration '" + strConfiguration + "' from domain '" + strDomain + "'"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail:" << strError; return false; } // Delegate to configurable domains return logResult( getConfigurableDomains()->deleteConfiguration(strDomain, strConfiguration, strError), strError); } bool CParameterMgr::restoreConfiguration(const string &strDomain, const string &strConfiguration, core::Results &errors) { string strError; LOG_CONTEXT("Restoring domain '" + strDomain + "''s configuration '" + strConfiguration + "' to parameter blackboard"); // Check tuning mode if (!checkTuningModeOn(strError)) { errors.push_back(strError); warning() << "Fail:" << strError; return false; } // Delegate to configurable domains return logResult( getConstConfigurableDomains()->restoreConfiguration( strDomain, strConfiguration, _pMainParameterBlackboard, _bAutoSyncOn, errors), strError); } bool CParameterMgr::saveConfiguration(const string &strDomain, const string &strConfiguration, string &strError) { LOG_CONTEXT("Saving domain '" + strDomain + "' configuration '" + strConfiguration + "' from parameter blackboard"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail:" << strError; return false; } // Delegate to configurable domains return logResult(getConfigurableDomains()->saveConfiguration( strDomain, strConfiguration, _pMainParameterBlackboard, strError), strError); } // Configurable element - domain association bool CParameterMgr::addConfigurableElementToDomain(const string &strDomain, const string &strConfigurableElementPath, string &strError) { LOG_CONTEXT("Adding configurable element '" + strConfigurableElementPath + "' to domain '" + strDomain + "'"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail: " << strError; return false; } CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(strConfigurableElementPath, &pLocatedElement, strError)) { warning() << "Fail: " << strError; return false; } // Convert element CConfigurableElement *pConfigurableElement = static_cast<CConfigurableElement *>(pLocatedElement); // Delegate core::Results infos; bool isSuccess = getConfigurableDomains()->addConfigurableElementToDomain( strDomain, pConfigurableElement, _pMainParameterBlackboard, infos); if (isSuccess) { info() << infos; } else { warning() << infos; } strError = utility::asString(infos); return isSuccess; } bool CParameterMgr::removeConfigurableElementFromDomain(const string &strDomain, const string &strConfigurableElementPath, string &strError) { LOG_CONTEXT("Removing configurable element '" + strConfigurableElementPath + "' from domain '" + strDomain + "'"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail:" << strError; return false; } CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(strConfigurableElementPath, &pLocatedElement, strError)) { warning() << "Fail:" << strError; return false; } // Convert element CConfigurableElement *pConfigurableElement = static_cast<CConfigurableElement *>(pLocatedElement); // Delegate return logResult(getConfigurableDomains()->removeConfigurableElementFromDomain( strDomain, pConfigurableElement, strError), strError); } bool CParameterMgr::split(const string &strDomain, const string &strConfigurableElementPath, string &strError) { LOG_CONTEXT("Splitting configurable element '" + strConfigurableElementPath + "' domain '" + strDomain + "'"); // Check tuning mode if (!checkTuningModeOn(strError)) { warning() << "Fail:" << strError; return false; } CElementLocator elementLocator(getSystemClass()); CElement *pLocatedElement = NULL; if (!elementLocator.locate(strConfigurableElementPath, &pLocatedElement, strError)) { warning() << "Fail: " << strError; return false; } // Convert element CConfigurableElement *pConfigurableElement = static_cast<CConfigurableElement *>(pLocatedElement); // Delegate core::Results infos; bool isSuccess = getConfigurableDomains()->split(strDomain, pConfigurableElement, infos); if (isSuccess) { info() << infos; } else { warning() << infos; } strError = utility::asString(infos); return isSuccess; } bool CParameterMgr::setElementSequence(const string &strDomain, const string &strConfiguration, const std::vector<string> &astrNewElementSequence, string &strError) { // Check tuning mode if (!checkTuningModeOn(strError)) { return false; } return getConfigurableDomains()->setElementSequence(strDomain, strConfiguration, astrNewElementSequence, strError); } bool CParameterMgr::getApplicationRule(const string &strDomain, const string &strConfiguration, string &strResult) { return getConfigurableDomains()->getApplicationRule(strDomain, strConfiguration, strResult); } bool CParameterMgr::setApplicationRule(const string &strDomain, const string &strConfiguration, const string &strApplicationRule, string &strError) { return getConfigurableDomains()->setApplicationRule( strDomain, strConfiguration, strApplicationRule, getConstSelectionCriteria()->getSelectionCriteriaDefinition(), strError); } bool CParameterMgr::clearApplicationRule(const string &strDomain, const string &strConfiguration, string &strError) { return getConfigurableDomains()->clearApplicationRule(strDomain, strConfiguration, strError); } bool CParameterMgr::importDomainsXml(const string &xmlSource, bool withSettings, bool fromFile, string &errorMsg) { // Check tuning mode if (!checkTuningModeOn(errorMsg)) { return false; } LOG_CONTEXT("Importing domains from " + (fromFile ? ("\"" + xmlSource + "\"") : "a user-provided buffer")); // Root element CConfigurableDomains *pConfigurableDomains = getConfigurableDomains(); bool importSuccess = wrapLegacyXmlImport(xmlSource, fromFile, withSettings, *pConfigurableDomains, "SystemClassName", errorMsg); if (importSuccess) { // Validate domains after XML import pConfigurableDomains->validate(_pMainParameterBlackboard); } return importSuccess; } bool CParameterMgr::importSingleDomainXml(const string &xmlSource, bool overwrite, bool withSettings, bool fromFile, string &errorMsg) { if (!checkTuningModeOn(errorMsg)) { return false; } LOG_CONTEXT("Importing a single domain from " + (fromFile ? ('"' + xmlSource + '"') : "a user-provided buffer")); // We initialize the domain with an empty name but since we have set the isDomainStandalone // context, the name will be retrieved during de-serialization auto standaloneDomain = utility::make_unique<CConfigurableDomain>(); if (!wrapLegacyXmlImport(xmlSource, fromFile, withSettings, *standaloneDomain, "", errorMsg)) { return false; } if (!getConfigurableDomains()->addDomain(*standaloneDomain, overwrite, errorMsg)) { return false; } // ownership has been transfered to the ConfigurableDomains object standaloneDomain.release(); return true; } bool CParameterMgr::wrapLegacyXmlImport(const string &xmlSource, bool fromFile, bool withSettings, CElement &element, const string &nameAttributeName, string &errorMsg) { CXmlDomainImportContext xmlDomainImportContext(errorMsg, withSettings, *getSystemClass()); // Selection criteria definition for rule creation xmlDomainImportContext.setSelectionCriteriaDefinition( getConstSelectionCriteria()->getSelectionCriteriaDefinition()); // It doesn't make sense to resolve XIncludes on an imported file because // we can't reliably decide of a "base url" _xmlDoc *doc = CXmlDocSource::mkXmlDoc(xmlSource, fromFile, false, xmlDomainImportContext); if (doc == NULL) { return false; } return xmlParse(xmlDomainImportContext, &element, doc, "", EParameterConfigurationLibrary, true, nameAttributeName); } bool CParameterMgr::serializeElement(std::ostream &output, CXmlSerializingContext &xmlSerializingContext, const CElement &element) const { if (!output.good()) { xmlSerializingContext.setError("Can't write XML: the output is in a bad state."); return false; } // Use a doc source by loading data from instantiated Configurable Domains CXmlMemoryDocSource memorySource(&element, _bValidateSchemasOnStart, element.getXmlElementName(), "parameter-framework", getVersion()); // Use a doc sink to write the doc data in a stream CXmlStreamDocSink sink(output); bool processSuccess = sink.process(memorySource, xmlSerializingContext); return processSuccess; } bool CParameterMgr::exportDomainsXml(string &xmlDest, bool withSettings, bool toFile, string &errorMsg) const { LOG_CONTEXT("Exporting domains to " + (toFile ? ('"' + xmlDest + '"') : "a user-provided buffer")); const CConfigurableDomains *configurableDomains = getConstConfigurableDomains(); return wrapLegacyXmlExport(xmlDest, toFile, withSettings, *configurableDomains, errorMsg); } bool CParameterMgr::exportSingleDomainXml(string &xmlDest, const string &domainName, bool withSettings, bool toFile, string &errorMsg) const { LOG_CONTEXT("Exporting single domain '" + domainName + "' to " + (toFile ? ('"' + xmlDest + '"') : "a user-provided buffer")); // Element to be serialized const CConfigurableDomain *requestedDomain = getConstConfigurableDomains()->findConfigurableDomain(domainName, errorMsg); if (requestedDomain == NULL) { return false; } return wrapLegacyXmlExport(xmlDest, toFile, withSettings, *requestedDomain, errorMsg); } bool CParameterMgr::wrapLegacyXmlExport(string &xmlDest, bool toFile, bool withSettings, const CElement &element, string &errorMsg) const { CXmlDomainExportContext context(errorMsg, withSettings, _bValueSpaceIsRaw, _bOutputRawFormatIsHex); if (toFile) { return wrapLegacyXmlExportToFile(xmlDest, element, context); } else { return wrapLegacyXmlExportToString(xmlDest, element, context); } } bool CParameterMgr::wrapLegacyXmlExportToFile(string &xmlDest, const CElement &element, CXmlDomainExportContext &context) const { try { std::ofstream output; // Force stream to throw instead of using fail/bad bit // in order to retreive an error message. output.exceptions(~std::ifstream::goodbit); output.open(xmlDest.c_str()); bool status = serializeElement(output, context, element); output.close(); // Explicit close to detect errors return status; } catch (std::ofstream::failure &e) { context.setError("Failed to open \"" + xmlDest + "\" for writing: " + e.what()); return false; } } bool CParameterMgr::wrapLegacyXmlExportToString(string &xmlDest, const CElement &element, CXmlDomainExportContext &context) const { std::ostringstream output; if (!serializeElement(output, context, element)) { return false; } xmlDest = output.str(); return true; } // For tuning, check we're in tuning mode bool CParameterMgr::checkTuningModeOn(string &strError) const { // Tuning Mode on? if (!_bTuningModeIsOn) { strError = "Tuning Mode must be on"; return false; } return true; } // Tuning mutex dynamic parameter handling std::mutex &CParameterMgr::getBlackboardMutex() { return _blackboardMutex; } // Blackboard reference (dynamic parameter handling) CParameterBlackboard *CParameterMgr::getParameterBlackboard() { return _pMainParameterBlackboard; } // Dynamic creation library feeding void CParameterMgr::feedElementLibraries() { // Global Configuration handling CElementLibrary *pFrameworkConfigurationLibrary = new CElementLibrary; pFrameworkConfigurationLibrary->addElementBuilder( "ParameterFrameworkConfiguration", new TElementBuilderTemplate<CParameterFrameworkConfiguration>()); pFrameworkConfigurationLibrary->addElementBuilder( "SubsystemPlugins", new TKindElementBuilderTemplate<CSubsystemPlugins>()); pFrameworkConfigurationLibrary->addElementBuilder( "Location", new TKindElementBuilderTemplate<CPluginLocation>()); pFrameworkConfigurationLibrary->addElementBuilder( "StructureDescriptionFileLocation", new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>()); pFrameworkConfigurationLibrary->addElementBuilder( "SettingsConfiguration", new TKindElementBuilderTemplate<CFrameworkConfigurationGroup>()); pFrameworkConfigurationLibrary->addElementBuilder( "ConfigurableDomainsFileLocation", new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>()); _pElementLibrarySet->addElementLibrary(pFrameworkConfigurationLibrary); // Parameter creation CElementLibrary *pParameterCreationLibrary = new CElementLibrary; pParameterCreationLibrary->addElementBuilder( "Subsystem", new CSubsystemElementBuilder(getSystemClass()->getSubsystemLibrary())); pParameterCreationLibrary->addElementBuilder( "ComponentType", new TNamedElementBuilderTemplate<CComponentType>()); pParameterCreationLibrary->addElementBuilder( "Component", new TNamedElementBuilderTemplate<CComponentInstance>()); pParameterCreationLibrary->addElementBuilder( "BitParameter", new TNamedElementBuilderTemplate<CBitParameterType>()); pParameterCreationLibrary->addElementBuilder( "BitParameterBlock", new TNamedElementBuilderTemplate<CBitParameterBlockType>()); pParameterCreationLibrary->addElementBuilder( "StringParameter", new TNamedElementBuilderTemplate<CStringParameterType>()); pParameterCreationLibrary->addElementBuilder( "ParameterBlock", new TNamedElementBuilderTemplate<CParameterBlockType>()); pParameterCreationLibrary->addElementBuilder( "BooleanParameter", new TNamedElementBuilderTemplate<CBooleanParameterType>()); pParameterCreationLibrary->addElementBuilder( "IntegerParameter", new TNamedElementBuilderTemplate<CIntegerParameterType>()); pParameterCreationLibrary->addElementBuilder( "LinearAdaptation", new TElementBuilderTemplate<CLinearParameterAdaptation>()); pParameterCreationLibrary->addElementBuilder( "LogarithmicAdaptation", new TElementBuilderTemplate<CLogarithmicParameterAdaptation>()); pParameterCreationLibrary->addElementBuilder( "EnumParameter", new TNamedElementBuilderTemplate<CEnumParameterType>()); pParameterCreationLibrary->addElementBuilder("ValuePair", new TElementBuilderTemplate<CEnumValuePair>()); pParameterCreationLibrary->addElementBuilder( "FixedPointParameter", new TNamedElementBuilderTemplate<CFixedPointParameterType>()); pParameterCreationLibrary->addElementBuilder( "FloatingPointParameter", new TNamedElementBuilderTemplate<CFloatingPointParameterType>); pParameterCreationLibrary->addElementBuilder( "SubsystemInclude", new CFileIncluderElementBuilder(_bValidateSchemasOnStart, getSchemaUri())); _pElementLibrarySet->addElementLibrary(pParameterCreationLibrary); // Parameter Configuration Domains creation CElementLibrary *pParameterConfigurationLibrary = new CElementLibrary; pParameterConfigurationLibrary->addElementBuilder( "ConfigurableDomain", new TElementBuilderTemplate<CConfigurableDomain>()); pParameterConfigurationLibrary->addElementBuilder( "Configuration", new TNamedElementBuilderTemplate<CDomainConfiguration>()); pParameterConfigurationLibrary->addElementBuilder("CompoundRule", new TElementBuilderTemplate<CCompoundRule>()); pParameterConfigurationLibrary->addElementBuilder( "SelectionCriterionRule", new TElementBuilderTemplate<CSelectionCriterionRule>()); _pElementLibrarySet->addElementLibrary(pParameterConfigurationLibrary); } bool CParameterMgr::getForceNoRemoteInterface() const { return _bForceNoRemoteInterface; } void CParameterMgr::setForceNoRemoteInterface(bool bForceNoRemoteInterface) { _bForceNoRemoteInterface = bForceNoRemoteInterface; } CParameterMgr::CommandHandler CParameterMgr::createCommandHandler() { auto commandHandler = utility::make_unique<CCommandHandler>(this); // Add command parsers for (const auto &remoteCommandParserItem : gastRemoteCommandParserItems) { commandHandler->addCommandParser( remoteCommandParserItem._pcCommandName, remoteCommandParserItem._pfnParser, remoteCommandParserItem._minArgumentCount, remoteCommandParserItem._pcHelp, remoteCommandParserItem._pcDescription); } return commandHandler; } bool CParameterMgr::isRemoteInterfaceRequired() { // The remote interface should only be started if the client didn't // explicitly forbid it and if the configuration file allows it. return (not _bForceNoRemoteInterface) and getConstFrameworkConfiguration()->isTuningAllowed(); } // Remote Processor Server connection handling bool CParameterMgr::handleRemoteProcessingInterface(string &strError) { LOG_CONTEXT("Handling remote processing interface"); if (not isRemoteInterfaceRequired()) { return true; } auto port = getConstFrameworkConfiguration()->getServerPort(); try { // The ownership of remoteComandHandler is given to Bg remote processor server. _pRemoteProcessorServer = new BackgroundRemoteProcessorServer(port, createCommandHandler()); } catch (std::runtime_error &e) { strError = string("ParameterMgr: Unable to create Remote Processor Server: ") + e.what(); return false; } if (_pRemoteProcessorServer == NULL) { strError = "ParameterMgr: Unable to create Remote Processor Server"; return false; } if (!_pRemoteProcessorServer->start(strError)) { ostringstream oss; oss << "ParameterMgr: Unable to start remote processor server on port " << port; strError = oss.str() + ": " + strError; return false; } info() << "Remote Processor Server started on port " << port; return true; } // Children typwise access CParameterFrameworkConfiguration *CParameterMgr::getFrameworkConfiguration() { return static_cast<CParameterFrameworkConfiguration *>(getChild(EFrameworkConfiguration)); } const CParameterFrameworkConfiguration *CParameterMgr::getConstFrameworkConfiguration() { return getFrameworkConfiguration(); } CSelectionCriteria *CParameterMgr::getSelectionCriteria() { return static_cast<CSelectionCriteria *>(getChild(ESelectionCriteria)); } const CSelectionCriteria *CParameterMgr::getConstSelectionCriteria() { return static_cast<const CSelectionCriteria *>(getChild(ESelectionCriteria)); } CSystemClass *CParameterMgr::getSystemClass() { return static_cast<CSystemClass *>(getChild(ESystemClass)); } const CSystemClass *CParameterMgr::getConstSystemClass() const { return static_cast<const CSystemClass *>(getChild(ESystemClass)); } // Configurable Domains CConfigurableDomains *CParameterMgr::getConfigurableDomains() { return static_cast<CConfigurableDomains *>(getChild(EConfigurableDomains)); } const CConfigurableDomains *CParameterMgr::getConstConfigurableDomains() { return static_cast<const CConfigurableDomains *>(getChild(EConfigurableDomains)); } const CConfigurableDomains *CParameterMgr::getConstConfigurableDomains() const { return static_cast<const CConfigurableDomains *>(getChild(EConfigurableDomains)); } // Apply configurations void CParameterMgr::doApplyConfigurations(bool bForce) { LOG_CONTEXT("Applying configurations"); CSyncerSet syncerSet; core::Results infos; // Check subsystems that need resync getSystemClass()->checkForSubsystemsToResync(syncerSet, infos); // Ensure application of currently selected configurations getConfigurableDomains()->apply(_pMainParameterBlackboard, syncerSet, bForce, infos); info() << infos; // Reset the modified status of the current criteria to indicate that a new configuration has // been applied getSelectionCriteria()->resetModifiedStatus(); } // Export to XML string bool CParameterMgr::exportElementToXMLString(const IXmlSource *pXmlSource, const string &strRootElementType, CXmlSerializingContext &&xmlSerializingContext, string &strResult) const { // Use a doc source by loading data from instantiated Configurable Domains CXmlMemoryDocSource memorySource(pXmlSource, false, strRootElementType); // Use a doc sink that write the doc data in a string ostringstream output; CXmlStreamDocSink streamSink(output); // Do the export bool bProcessSuccess = streamSink.process(memorySource, xmlSerializingContext); strResult = output.str(); return bProcessSuccess; } bool CParameterMgr::logResult(bool isSuccess, const std::string &result) { std::string log = result.empty() ? "" : ": " + result; if (isSuccess) { info() << "Success" << log; } else { warning() << "Fail" << log; } return isSuccess; } log::details::Info CParameterMgr::info() { return _logger.info(); } log::details::Warning CParameterMgr::warning() { return _logger.warning(); }