Commit 6e62af04 authored by Micha Mueller's avatar Micha Mueller
Browse files

Try to switch the configurators to non-virtual interface template

parent 8887cb79
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <map>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
typedef struct { typedef struct {
std::string mqttPrefix; std::string mqttPrefix;
...@@ -20,10 +26,15 @@ typedef struct { ...@@ -20,10 +26,15 @@ typedef struct {
} pluginSettings_t; } pluginSettings_t;
/** /**
* Base class, which defines the interface for the configurators in the shared dynamic libraries. * Non-virtual interface template for the configurators.
* This base class shall not be constructed on itw own.
*/ */
template <typename S>
class Configurator { class Configurator {
//the template shall only be instantiated for the sensors corresponding to the configurator
static_assert(std::is_base_of<Sensor, S>::value, "S must derive from Sensor!");
typedef std::map<std::string, S> sensorMap_t;
public: public:
Configurator() : _cacheInterval(900000) {} Configurator() : _cacheInterval(900000) {}
...@@ -35,47 +46,175 @@ public: ...@@ -35,47 +46,175 @@ public:
/** /**
* Read in the given configuration * Read in the given configuration
*
* @param cfgPath Path to the config-file * @param cfgPath Path to the config-file
* @return true on success, false otherwise *
* @return True on success, false otherwise
*/ */
virtual bool readConfig(std::string cfgPath) { bool readConfig(std::string cfgPath) {
_cfgPath = cfgPath; _cfgPath = cfgPath;
return true;
boost::property_tree::iptree cfg;
boost::property_tree::read_info(cfgPath, cfg);
//read global variables (if present overwrite those from global.conf)
BOOST_FOREACH(boost::property_tree::iptree::value_type &global, cfg.get_child("global")) {
if (boost::iequals(global.first, "mqttprefix")) {
_mqttPrefix = global.second.data();
if (_mqttPrefix[_mqttPrefix.length()-1] != '/') {
_mqttPrefix.append("/");
}
LOG(debug) << " Using own MQTT-Prefix " << _mqttPrefix;
} else if (boost::iequals(global.first, "cacheInterval")) {
_cacheInterval = stoul(global.second.data());
LOG(debug) << " Using own caching interval " << _cacheInterval << " [s]";
_cacheInterval *= 1000;
} else {
LOG(error) << " Value \"" << global.first << "\" not recognized. Omitting...";
}
}
//read template sensors
BOOST_FOREACH(boost::property_tree::iptree::value_type &sens, cfg.get_child("templates")) {
if (boost::iequals(sens.first, "sensor")) {
LOG(debug) << "Template Sensor \"" << sens.second.data() << "\"";
if (!sens.second.empty()) {
S sensor(sens.second.data());
if(readSensor(sensor, sens.second)) {
_templateSensors.insert(sensorMap_t::value_type(sensor.getName(), sensor));
} else {
LOG(warning) << "Template sensor \"" << sens.second.data() << "\" has bad values! Ignoring...";
}
}
}
}
//read in plugin specific stuff (including actual sensors)
return derivedReadConfig(cfg);
} }
/** /**
* Clear internal storage and read in the configuration again. * Clear internal storage and read in the configuration again.
*
* @return True on success, false otherwise
*/ */
virtual bool reReadConfig() { bool reReadConfig() {
for (auto s : _sensors) { for (auto s : _sensors) {
s->stopPolling(); s->stopPolling();
} }
derivedReReadConfig();
for (auto s : _sensors) { for (auto s : _sensors) {
delete s; delete s;
} }
_sensors.clear(); _sensors.clear();
return this->readConfig(_cfgPath); _templateSensors.clear();
return readConfig(_cfgPath);
} }
virtual void setGlobalSettings(const pluginSettings_t& pluginSettings) { /**
* Sets internal variables with the ones provided by pluginSettings.
* This method should be called once after constructing a configurator
* to provide him with the global default values.
*
* @param pluginSettings Struct with global default settings for the plugins.
*/
void setGlobalSettings(const pluginSettings_t& pluginSettings) {
_mqttPrefix = pluginSettings.mqttPrefix; _mqttPrefix = pluginSettings.mqttPrefix;
_cacheInterval = pluginSettings.cacheInterval; _cacheInterval = pluginSettings.cacheInterval;
derivedSetGlobalSettings(pluginSettings);
} }
/**
* Get all sensors
*
* @return Vector containing pointers to all sensors of this plugin
*/
std::vector<Sensor*>& getSensors() { std::vector<Sensor*>& getSensors() {
return _sensors; return _sensors;
} }
protected: protected:
std::string _cfgPath; /**
std::string _mqttPrefix; * Non-virtual interface method for class-internal use only.
unsigned int _cacheInterval; * Reads and sets the common base values of a sensor, then calls
* the corresponding derived function.
*
* @param sensor The sensor for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*
* @return True on success, false otherwise
*/
bool readSensor(S& sensor, boost::property_tree::iptree& config) {
//read in base values
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (boost::iequals(val.first, "interval")) {
sensor.setInterval(stoull(val.second.data()));
} else if (boost::iequals(val.first, "mqttsuffix")) {
sensor.setMqtt(sensor.getMqtt() + val.second.data());
} else if (boost::iequals(val.first, "minValues")) {
sensor.setMinValues(stoull(val.second.data()));
} else {
//do nothing. Derived function should read in other values
}
}
sensor.setCacheInterval(_cacheInterval);
LOG(debug) << " MQTT : " << sensor.getMqtt();
LOG(debug) << " Interval : " << sensor.getInterval();
LOG(debug) << " minValues: " << sensor.getMinValues();
return derivedReadSensor(sensor, config);
}
/**
* Pure virtual interface method, responsible for reading the plugin-specific
* configuration part.
*
* @param cfg The (root) boost property tree from the plugins configuration file
*
* @return True on success, false otherwise
*/
virtual bool derivedReadConfig(boost::property_tree::iptree& cfg) = 0;
/**
* Pure virtual interface method, responsible for the plugin specific part if
* re-reading the config.
*/
virtual void derivedReReadConfig() = 0;
/**
* Pure virtual interface method, responsible for setting global values specifically
* for its plugin.
*
* @param pluginSettings The struct with global default plugin settings
*/
virtual void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) = 0;
/**
* Pure virtual interface method, responsible for reading plugin-specific sensor
* values.
*
* @param sensor The sensor for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*
* @return True on success, false otherwise
*/
virtual bool derivedReadSensor(S& sensor, boost::property_tree::iptree& config) = 0;
std::string _cfgPath;
std::string _mqttPrefix;
unsigned int _cacheInterval;
std::vector<Sensor*> _sensors; std::vector<Sensor*> _sensors;
sensorMap_t _templateSensors;
boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg; boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;
}; };
//typedef for more readable usage of create()- and destroy()-methods, required for dynamic libraries //typedef for more readable usage of create()- and destroy()-methods, required for dynamic libraries
typedef Configurator* create_t(); typedef Configurator<Sensor>* create_t();
typedef void destroy_t(Configurator*); typedef void destroy_t(Configurator<Sensor>*);
#endif /* SRC_CONFIGURATOR_H_ */ #endif /* SRC_CONFIGURATOR_H_ */
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
typedef struct { typedef struct {
std::string id; std::string id;
void* DL; void* DL;
Configurator* configurator; Configurator<Sensor>* configurator;
create_t* create; create_t* create;
destroy_t* destroy; destroy_t* destroy;
} dl_t; } dl_t;
......
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
#include "SNMPConfigurator.h" #include "SNMPConfigurator.h"
#include <boost/foreach.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/algorithm/string.hpp>
SNMPConfigurator::SNMPConfigurator() { SNMPConfigurator::SNMPConfigurator() {
/* Initialize SNMP library */ /* Initialize SNMP library */
init_snmp("dcdbpusher_SNMPplugin"); init_snmp("dcdbpusher_SNMPplugin");
...@@ -18,45 +14,9 @@ SNMPConfigurator::SNMPConfigurator() { ...@@ -18,45 +14,9 @@ SNMPConfigurator::SNMPConfigurator() {
SNMPConfigurator::~SNMPConfigurator() {} SNMPConfigurator::~SNMPConfigurator() {}
bool SNMPConfigurator::readConfig(std::string cfgPath) { bool SNMPConfigurator::derivedReadConfig(boost::property_tree::iptree& cfg) {
Configurator::readConfig(cfgPath);
boost::property_tree::iptree cfg;
boost::property_tree::read_info(cfgPath, cfg);
std::string mqttPartConnection; std::string mqttPartConnection;
//read global variables (if present overwrite those from global.conf)
BOOST_FOREACH(boost::property_tree::iptree::value_type &global, cfg.get_child("global")) {
if (boost::iequals(global.first, "mqttprefix")) {
_mqttPrefix = global.second.data();
if (_mqttPrefix[_mqttPrefix.length()-1] != '/') {
_mqttPrefix.append("/");
}
LOG(debug) << " Using own MQTT-Prefix " << _mqttPrefix;
} else if (boost::iequals(global.first, "cacheInterval")) {
_cacheInterval = stoul(global.second.data());
LOG(debug) << " Using own caching interval " << _cacheInterval << " [s]";
_cacheInterval *= 1000;
} else {
LOG(error) << " Value \"" << global.first << "\" not recognized. Omitting...";
}
}
//read template sensors
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, cfg.get_child("templates")) {
if (boost::iequals(sensor.first, "sensor")) {
LOG(debug) << "Template Sensor \"" << sensor.second.data() << "\"";
if (!sensor.second.empty()) {
SNMPSensor snmpSensor(sensor.second.data());
if(readSensor(snmpSensor, sensor.second)) {
_templateSensors.insert(sensorMap_t::value_type(snmpSensor.getName(), snmpSensor));
} else {
LOG(warning) << "Template sensor \"" << sensor.second.data() << "\" has bad values! Ignoring...";
}
}
}
}
BOOST_FOREACH(boost::property_tree::iptree::value_type &connection, cfg.get_child("connections")) { BOOST_FOREACH(boost::property_tree::iptree::value_type &connection, cfg.get_child("connections")) {
if (boost::iequals(connection.first, ("connection"))) { if (boost::iequals(connection.first, ("connection"))) {
LOG(debug) << "Connection " << connection.second.data(); LOG(debug) << "Connection " << connection.second.data();
...@@ -186,27 +146,25 @@ bool SNMPConfigurator::readConfig(std::string cfgPath) { ...@@ -186,27 +146,25 @@ bool SNMPConfigurator::readConfig(std::string cfgPath) {
return true; return true;
} }
bool SNMPConfigurator::readSensor(SNMPSensor& sensor, boost::property_tree::iptree& config) { void SNMPConfigurator::derivedReReadConfig() {
sleep(5);
_connections.clear();
}
bool SNMPConfigurator::derivedReadSensor(SNMPSensor& sensor, boost::property_tree::iptree& config) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) { BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (boost::iequals(val.first, "interval")) { if (boost::iequals(val.first, "interval")) {
sensor.setInterval(stoull(val.second.data())); //avoid unnecessary "Value not recognized" messages
} else if (boost::iequals(val.first, "mqttsuffix")) { } else if (boost::iequals(val.first, "mqttsuffix")) {
sensor.setMqtt(sensor.getMqtt() + val.second.data());
} else if (boost::iequals(val.first, "minValues")) { } else if (boost::iequals(val.first, "minValues")) {
sensor.setMinValues(stoull(val.second.data())); } else if (boost::iequals(val.first, "default")) {
} else if (boost::iequals(val.first, "OID")) { } else if (boost::iequals(val.first, "OID")) {
sensor.setOID(sensor.getConnection()->getOIDPrefix() + "." + val.second.data()); sensor.setOID(sensor.getConnection()->getOIDPrefix() + "." + val.second.data());
} else if (boost::iequals(val.first, "default")) {
//avoid unnecessary "Value not recognized" message
} else { } else {
LOG(warning) << " Value \"" << val.first << "\" not recognized. Omitting..."; LOG(warning) << " Value \"" << val.first << "\" not recognized. Omitting...";
} }
} }
sensor.setCacheInterval(_cacheInterval);
LOG(debug) << " MQTT : " << sensor.getMqtt();
LOG(debug) << " Interval : " << sensor.getInterval();
LOG(debug) << " minValues: " << sensor.getMinValues();
LOG(debug) << " OID : " << sensor.getOIDString(); LOG(debug) << " OID : " << sensor.getOIDString();
return true; return true;
} }
...@@ -13,49 +13,27 @@ ...@@ -13,49 +13,27 @@
#include "SNMPSensor.h" #include "SNMPSensor.h"
#include "SNMPConnection.h" #include "SNMPConnection.h"
#include <string>
#include <vector>
#include <map>
#include <list> #include <list>
#include <boost/property_tree/ptree.hpp>
class SNMPConfigurator : public Configurator { class SNMPConfigurator : public Configurator<SNMPSensor> {
typedef std::list<SNMPConnection> connectionList_t; typedef std::list<SNMPConnection> connectionList_t;
typedef std::map<std::string, SNMPSensor> sensorMap_t;
public: public:
SNMPConfigurator(); SNMPConfigurator();
virtual ~SNMPConfigurator(); virtual ~SNMPConfigurator();
/** protected:
* Read in the configuration for snmp-connections and sensors. bool derivedReadConfig(boost::property_tree::iptree& cfg) final;
* @param cfgPath Path + name of the config-file
* @return true on success, false otherwise
*/
bool readConfig(std::string cfgPath);
//Overwrite from Configurator void derivedReReadConfig() final;
bool reReadConfig() {
for (auto s : _sensors) {
s->stopPolling();
}
sleep(10);
_connections.clear();
_templateSensors.clear();
return Configurator::reReadConfig();
}
private: void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) final {/*nothing to overwrite*/}
/**
* Set the variables of sensor according to the values specified in config. bool derivedReadSensor(SNMPSensor& sensor, boost::property_tree::iptree& config) final;
* @param sensor The sensor to be configured
* @param config A property(sub)tree containing the values
*/
bool readSensor(SNMPSensor& sensor, boost::property_tree::iptree& config);
private:
connectionList_t _connections; connectionList_t _connections;
sensorMap_t _templateSensors;
}; };
extern "C" Configurator* create() { extern "C" Configurator* create() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment