Skip to content

Commit

Permalink
[config] Process config.d files in alnum order
Browse files Browse the repository at this point in the history
Each configuration file is kept in separate QSettings object and lookup
for values is done in load order - which is reverse from convention
where 10-something.conf can be overridden with 20-something-else.conf.

Change evaluation so that latter files can override earlier ones under
assumption that so far there have been no devices that would actually
employ more than one config.d file and thus glitches are unlikely.

Also merge data from all settings files into a single QSettings object
i.e. trade a bit more complex startup for simpler lookups during runtime.

The primary config file, if specified, still overrides any settings made
from config.d files.

Rename 90-sensord-default.conf to 10-sensord-default.conf so that it
still is 10 points up from the minimum priority.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed May 24, 2018
1 parent cdea3ec commit 4a04b3e
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 68 deletions.
File renamed without changes.
98 changes: 36 additions & 62 deletions core/config.cpp
Expand Up @@ -39,94 +39,68 @@ Config::Config() {
}

Config::~Config() {
clearConfig();
}

void Config::clearConfig() {
foreach(QSettings* setting, settings)
delete setting;
settings.clear();
m_settings.clear();
}

bool Config::loadConfig(const QString &defConfigPath, const QString &configDPath) {
Config *config = NULL;
/* Not having config files is ok, failing to load one that exists is not */
bool ret = true;

/* Check/create new static config */
if (static_configuration) {
config = static_configuration;
} else {
config = new Config();
if (!static_configuration) {
static_configuration = new Config();
}

if (!config->loadConfigFile(defConfigPath))
ret = false;

/* Scan config.d dir */
QStringList fileList;
if(!configDPath.isEmpty())
{
/* Process config.d dir in alnum order */
if (!configDPath.isEmpty()) {
QDir dir(configDPath, "*.conf", QDir::Name, QDir::Files);
fileList = dir.entryList();
foreach(const QString& file, fileList)
{
if (!config->loadConfigFile(dir.absoluteFilePath(file)))
foreach(const QString &file, dir.entryList()) {
if (!static_configuration->loadConfigFile(dir.absoluteFilePath(file))) {
ret = false;
}
}
}

static_configuration = config;

/* Primary config file overrides config.d */
if (!defConfigPath.isEmpty() && QFile::exists(defConfigPath) ) {
if (!static_configuration->loadConfigFile(defConfigPath))
ret = false;
}
return ret;
}

bool Config::loadConfigFile(const QString &configFileName) {
if(!QFile::exists(configFileName))
{
/* Success means the file was loaded and processed without hiccups */
bool loaded = false;
if (!QFile::exists(configFileName)) {
sensordLogW() << "File does not exists \"" << configFileName << "\"";
return false;
}
QSettings* setting = new QSettings(configFileName, QSettings::IniFormat);
if(setting->status() == QSettings::NoError) {
settings.append(setting);
sensordLogD() << "Config file \"" << configFileName << "\" successfully loaded";
return true;
} else {
QSettings merge(configFileName, QSettings::IniFormat);
QSettings::Status status(merge.status());
if (status == QSettings::FormatError ) {
sensordLogW() << "Configuration file \"" << configFileName << "\" is in wrong format";
} else if (status != QSettings::NoError) {
sensordLogW() << "Unable to open \"" << configFileName << "\" configuration file";
} else {
foreach (const QString &key, merge.allKeys()) {
m_settings.setValue(key, merge.value(key));
}
loaded = true;
}
}
else if(setting->status() == QSettings::AccessError)
sensordLogW() << "Unable to open \"" << configFileName << "\" configuration file";
else if(setting->status() == QSettings::FormatError)
sensordLogW() << "Configuration file \"" << configFileName << "\" is in wrong format";
else
sensordLogW() << "Configuration file \"" << configFileName << "\" parsing failed to unknown error: " << setting->status();
delete setting;
return false;
return loaded;
}

QVariant Config::value(const QString &key) const {
/* Iterate through configs so that keys in the first files
* have preference over the last.
*/
foreach(QSettings* setting, settings) {
if(setting->contains(key))
{
QVariant var = setting->value(key, QVariant());
if(var.isValid())
sensordLogD() << "Value for key '" << key << "': " << var.toString();
return var;
}
QVariant var = m_settings.value(key, QVariant());
if(var.isValid()) {
sensordLogT() << "Value for key" << key << ":" << var.toString();
}
return QVariant();
return var;
}

QStringList Config::groups() const
{
QStringList groups;
foreach(QSettings* setting, settings) {
foreach(const QString& group, setting->childGroups()) {
if(!groups.contains(group))
groups << group;
}
}
QStringList groups = m_settings.childGroups();
return groups;
}

Expand Down
2 changes: 1 addition & 1 deletion core/config.h
Expand Up @@ -136,7 +136,7 @@ class Config
*/
void clearConfig();

QList<QSettings*> settings; /**< parsed QSettings */
QSettings m_settings; /**< parsed QSettings */
};

template<typename T>
Expand Down
3 changes: 2 additions & 1 deletion doc/PLUGIN-GUIDE
Expand Up @@ -221,7 +221,8 @@ Sensorfw supports multiple configuration files. There are two locations:
(1) /etc/sensorfw/sensord.conf
(2) /etc/sensorfw/sensord.conf.d/

Any option set in (1) will override options set in any of the files in (2). Files in (2) are given priority based on alphanumeric order. Using double-digits as the beginning of the filename for clarity is encouraged.
Any option set in (1) will override options set in any of the files in (2). Files in (2) are processed in alpha-numerical order, and later files can override settings from earlier files. Using double-digits as the beginning of the filename for clarity is encouraged.


Configuration files contain sections for different HW. These sections should connect plugin metanames (sampleadaptor) with the real plugin that should be used (sampleadaptor-inputdev). The configuration file also contains option 'deviceId', which specifies which section should be used. This will be removed once we have automatic detection of underlying HW in place.

Expand Down
6 changes: 3 additions & 3 deletions doc/mainpage.h
Expand Up @@ -694,9 +694,9 @@ Sensorfw supports multiple configuration files. There are two locations:
(1) /etc/sensorfw/sensord.conf
(2) /etc/sensorfw/sensord.conf.d/

Any option set in (1) will override options set in any of the files in (2). Files in (2) are given
priority based on alphanumeric order. Using double-digits as the beginning of the filename for
clarity is encouraged.
Any option set in (1) will override options set in any of the files in (2). Files in (2) are
processed in alpha-numerical order, and later files can override settings from earlier files.
Using double-digits as the beginning of the filename for clarity is encouraged.

Configuration files contain sections for different HW. These sections should connect plugin
metanames (sampleadaptor) with the real plugin that should be used (sampleadaptor-inputdev).
Expand Down
2 changes: 1 addition & 1 deletion sensorfw.pro
Expand Up @@ -104,7 +104,7 @@ equals(QT_MAJOR_VERSION, 5): {
DBUSCONFIGFILES.path = /etc/dbus-1/system.d
INSTALLS += DBUSCONFIGFILES

SENSORDCONFIGFILES.files = config/90-sensord-default.conf
SENSORDCONFIGFILES.files = config/10-sensord-default.conf
SENSORDCONFIGFILES.path = /etc/sensorfw/sensord.conf.d
INSTALLS += SENSORDCONFIGFILES

Expand Down

0 comments on commit 4a04b3e

Please sign in to comment.